因此,我最近写了一篇有关旧的,可靠的Apache Commons StringUtils的文章 ,该文章引起了一些评论,其中之一是Google Guava提供了更好的连接和拆分字符串的机制。 我必须承认,这是我尚未探索的番石榴的一个角落。 因此,我认为应该仔细研究一下,并与StringUtils进行比较,我不得不承认,我对自己的发现感到惊讶。
肯定有许多不同的方法可以做到这一点吗?
Guava和StringUtils确实采取了风格上不同的方法。 让我们从基本用法开始。
// Apache StringUtils...
String[] tokens1 = StringUtils.split('one,two,three',',');// Guava splitter...
Iterable<String> tokens2 = Splitter.on(',').split('one,two,three');
因此,我的第一个观察结果是Splitter更面向对象。 您必须创建一个拆分器对象,然后使用该对象进行拆分。 而StringUtils拆分器方法使用更具功能性的样式以及静态方法。
在这里,我更喜欢Splitter。 需要一个可重用的拆分器来拆分逗号分隔的列表吗? 一个拆分器还可以修剪开头和结尾的空白,并忽略空元素? 没问题:
Splitter niceCommaSplitter = Splitter.on(',').omitEmptyString().trimResults();niceCommaSplitter.split('one,, two, three'); //'one','two','three'
niceCommaSplitter.split(' four , five '); //'four','five'
这看起来真的很有用,还有其他区别吗?
还要注意的另一件事是Splitter
返回一个Iterable<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);
在我的机器上,以下时间输出:
594
31
番石榴的Splitter快将近10倍!
现在,这比我预期的要大得多,Splitter比StringUtils快10倍以上。 怎么会这样? 好吧,我怀疑这与返回类型有关。 Splitter
返回一个Iterable<String>
,而StringUtils.split
为您提供一个字符串数组! 因此, Splitter
实际上不需要创建新的String
对象。
还值得注意的是,您可以缓存您的Splitter对象,从而实现更快的运行时间。
番石榴的Splitter每次都赢吗?
稍等一下。 这还不是全部。 注意我们实际上对字符串的结果没有做任何事情吗? 就像我提到的,似乎Splitter实际上并没有创建任何新的Strings。 我怀疑这实际上是将其推迟到它返回的Iterator对象。
那么我们可以测试一下吗?
当然可以 以下是一些代码,可以反复检查生成的子字符串的长度:
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);Splitter splitter = Splitter.on(',');
start = System.currentTimeMillis();
for(int i=0; i<1000000; i++) {Iterable<String> numbers = splitter.split(numberList);for(String number : numbers) {number.length();}}
System.out.println(System.currentTimeMillis() - start);
在我的机器上,输出:
609
2048
番石榴的Splitter慢了将近4倍!
确实,我期望它们的速度差不多,或者说番石榴速度更快,所以这是另一个令人惊讶的结果。 看起来,通过返回Iterable,Splitter可以立即获得收益,从而可以长期承受痛苦。 确保性能测试实际上在测试有用的东西在这里也有道理。
总之,我想我大多数时候仍会使用Splitter。 在小型列表上,性能差异可以忽略不计,而Splitter的使用感觉更好。 仍然令我感到惊讶的是,如果您要拆分很多字符串,而性能是一个问题,则可能值得考虑切换回Commons StringUtils。
参考: Tom's Programming Blog博客上我们JCG合作伙伴 Tom Jefferys的Guava Splitter vs StringUtils 。
翻译自: https://www.javacodegeeks.com/2012/12/guava-splitter-vs-stringutils.html