日期:2014-05-16  浏览次数:20926 次

Google Guava Splitter 对比 Apache StringUtils
Guava Splitter vs StringUtils

最近写了关于apache commons的StringUtils提供的常用功能介绍,见链接(http://vipcowrie.iteye.com/blog/1513017),但是我们知道google的guava也提供了一些字符串处理的常见功能,所以,我在本文将对两者的字符串分割函数做一次比较详细的对比(结果比较surprise)。

区别
首先看基本的使用方法:

// Apache StringUtils...
String[] tokens1= StringUtils.split("one,two,three",',');
 
// Google Guava splitter...
Iteratable<String> tokens2 = Splitter.on(','),split("one,two,three");


很明显,google提供的方法更加的面向对象一点,因为它要先创建一个Splitter对象,然后使用它来分割字符串,而apache的方法则有点函数式编程的味道,它的方法都是静态的。

这里我更加倾向于采用google的splitter,因为这个对象是可以重用的,且可以在其上附加更多的功能,比如trim,去掉空的元素等,一切都很简单。
Splitter niceCommaSplitter = Splitter.on(',') .omitEmptyString().trimResults();
niceCommaSplitter.split("one,, two,  three"); //"one","two","three"
niceCommaSplitter.split("  four  ,  five  "); //"four","five"



看起来有点用,还有其他区别么?
另外一个需要注意的地方就是Splitter返回的是Iteratable<String>,而StringUtils.split返回的是一个String数组。

大部分使用分隔符的情况是我们需要对字符串按照分隔符进行遍历处理,仅此而已。
下面就是常用的代码性能对比的例子:
final String numberList = "One,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten";

long start = System.currentTimeMillis();  
for(int i=0; i<1000000; i++) {
    StringUtils.split(numberList , ',');   
}
System.out.println(System.currentTimeMillis() - start);
  
start = System.currentTimeMillis();
for(int i=0; i<1000000; i++) {
    Splitter.on(',').split(numberList );
}
System.out.println(System.currentTimeMillis() - start);
代码很简单,就是都对同一个字符串进行100万次的分隔操作,看看时间上的区别,结果如下:
983
165
很明显,guava的速度快很多,这个程序如果运行在每天处理大量字符串的服务中,那么性能差异更加明显。我想其中的原因是Splitter返回的是Iterable<String>,而StringUtils.split返回的是一个String[],需要创建新的String对象,导致耗时增加。

如果我们对Splitter对象缓存,那么速度提高更多:
start = System.currentTimeMillis();
    Splitter s = Splitter.on(',');
    for (int i = 0; i < 1000000; i++) {
      s.split(numberList);
    }
    System.out.println(System.currentTimeMillis() - start);
结果为12,神奇吧,呵呵

别急,结果还没有出来,目前我们还没有对结果进行处理。我们试试对上面的结果进行处理:
final String numberList = "One,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten";
    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
      final String[] numbers = StringUtils.split(numberList, ',');
      for (String number : numbers) {
        number.length();
      }
    }
    System.out.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
      Iterable<String> is = Splitter.on(',').split(numberList);
      for(String s:is) {
        s.length();
      }
    }
    System.out.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
    Splitter sp = Splitter.on(',');
    for (int i = 0; i < 1000000; i++) {
      Iterable<String> is =  sp.split(numberList);
      for(String s:is) {
        s.length();
      }
    }
    System.out.println(System.currentTimeMillis() - start);


结果再次令人惊奇:
851
2967
2514


guava比apache 的StringUtils慢3倍。

结论:
很明显,guava把处理时间较长的操作延迟到后面了,前期处理比较快。无论如何,我还是比较倾向于采用guava处理常见的字符串分隔任务,如果你要处理大量分隔后的字符串,且对性能比较关注,那可以使用StringUtils.split。
1 楼 loookto 2012-06-21  
final String numberList = "One,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten";   
		
		long strtime=System.currentTimeMillis();
		numberList.split(",");
		System.out.println(System.currentTimeMillis()-strtime);
		
		strtime=System.currentTimeMillis();
		StringUtils.split(numberList,",");
		System.out.println(System.currentTimeMillis()-strtime);
		
		strtime=System.curren