JDK的方法是最优的吗?

来源:互联网 发布:抽风散热器 知乎 编辑:程序博客网 时间:2024/04/28 06:12

        注:本文中使用JDK1.6版本。

        Java从一开始就提供了丰富的类库,这也是其受到广泛使用的一个重要原因。一般来说,类库中的方法经过多年的实践,也的确有很多值得学习的地方,但是针对具体的应用而言,类库的方法真的是最优的吗?
        以String为例,String是Java中最重要的几个类之一,提供了数十个方法,其中的一个格式化方法是:
    public static String format(String format, Object ... args)

        此方法提供了丰富的使用方法,如格式化为指定进制的数据,千分位分隔等,以及我们最常用的占位符替换的方法:

    String.format(“This is my %s”, “house”);
       正因为format方法提供了丰富的功能,使得其牺牲了一些性能上的要求,在一些要求极致性能且需求较为简单的地方就并不适合直接使用。下面的例子将通过比较自定义的format方法和类库中的format方法来对二者的性能作一个对比:
 
/** *=============================================================== * @author:       jiehao * @date:         2016年6月5日 上午11:48:51 *=============================================================== * 修订日期                                                         修订人                                                    描述 */package com.zjh.importnew.articles; import org.junit.Test; /** * <p>测试String的类库方法和自己简单实现方法的性能差异  * @author jiehao * @date   2016年6月5日 上午11:48:51 * @see  * @since   V1.0  * @modified TODO */public class StringTest {/** * <p>自定义format方法 * <p>仅针对%s这种占位符作替换 * @param strSource 原始字符串 * @param strFrom 待替换的不定字符数组 * @return 替换后的字符串 * @author jiehao * @date   2016年6月5日 上午11:50:11 * @since   V1.0 * @see    * @modified TODO */public static String format(String strSource, String... strFrom) {  if (strSource == null || strFrom == null) {      return strSource;   }  int i = 0;<span style="font-family: Arial, Helvetica, sans-serif;">  </span>  StringBuffer buffer = new StringBuffer();  int k=0;  while ((i = strSource.indexOf("%s")) >= 0) {    buffer.append(strSource.substring(0, i));    buffer.append(strFrom[k++]);    strSource = strSource.substring(i + 2, strSource.length());  }  buffer.append(strSource);  return buffer.toString();}
 
  /** * <p>单元测试 * <p>由于机器、环境、编译优化等差异,测试效果略有差异 * @author jiehao * @date   2016年6月5日 上午11:58:19 * @since   V1.0 * @see    * @modified TODO */@Testpublic void testCompareFormat(){  String source = "StringTest replace 1st value= %s, 2nd value = %s.";  String firstValue = "testCompareFormat1";  String secondValue = "testCompareFormat2";  int loopNum = 1000000;  long startTime1 = System.currentTimeMillis();  String afterLib = null;  for (int i = 0; i < loopNum; i++) {    afterLib = String.format(source, firstValue, secondValue);  }  long endTime1 = System.currentTimeMillis();  System.out.println("source = " + source + ", after format in lib = " + afterLib + ", time = " + (endTime1 - startTime1) + "ms");   long startTime2 = System.currentTimeMillis();  String afterMySelf = null;  for (int i = 0; i < loopNum; i++) {    afterMySelf = format(source, firstValue, secondValue);  }  long endTime2 = System.currentTimeMillis();  System.out.println("source = " + source + ", after format in myself = " + afterMySelf + ", time = " + (endTime2 - startTime2) + "ms");}}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
        测试结果表明:如果只是要求替换字符串中的”%s”占位符这种应用,自定义的接口方法甚至比format快上五六倍以上。笔者曾经的系统中就遇到过每天数十亿级的替换,每天累积下来的时间并不少,此时用自带的String.format方法显然并非最优方案。另一方面,为了实现类库中format丰富的功能,其内部是由一个复杂的正则表达式去匹配的,在并发时会大量消耗CPU资源,对服务器性能造成一定的影响。
      小结一下:
      1、Java某些类库(包括一些广泛应用的第三方jar)并非十全十美,如广受诟病的Date和Calander(好消息是,这两个类在JDK1.8中终于重新实现了),所以针对高性能的的场景,不要过度迷信类库的方法,类库方法未必是最优方案,需要具体问题具体解决。
      2、但在绝大多数情况下,类库方法都更加灵活和强大,依然是我们的首选。这种首选不仅仅体现在性能(大部分类库方法的性能都很好)和使用范围上,而且能减少项目的维护成本,享受版本更替时类库无形之间带来的改进。正如Joshua Bloch在《Effective Java》中指出的那样需要“谨慎地进行优化”,除非能带来明确地提升,否则类库依然是第一选择。

0 0
原创粉丝点击