看《Java程序性能优化-让你的Java程序更快、更稳定》一书,在提到字符串分割的性能优化方面,提到了String自带的split方法,使用StringTokenizer,以及使用String.indexOf3种方式做测试,效率JDK<StringTokenizer<indexOf。 但我本机测试结果却不同,本机测试的结果是StringTokenizer<StringUtils(apache commons-lang包)<JDK<indexOf。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static void spliteTest(String testType) {
StringBuffer stringBuffer = new StringBuffer();
String str = null;
String SPLIT = ","; // 分隔符
int MAX = 10000; // 分割10000次
// 构造一个包含1000个分隔符的长字符串
for (int i=0;i<1000;i++) {
stringBuffer.append(i+SPLIT);
}
str = stringBuffer.toString();
long start = System.currentTimeMillis();
switch (testType) {
case "jdk":
for (int i=0;i<MAX;i++) {
str.split(SPLIT);
}
System.out.println(testType + " cost " + (System.currentTimeMillis() - start));
break;
case "stringTokenizer":
StringTokenizer stringTokenizer = new StringTokenizer(str,SPLIT);
for (int i=0;i<MAX;i++) {
while (stringTokenizer.hasMoreTokens()) {
stringTokenizer.nextToken();
}
stringTokenizer = new StringTokenizer(str,SPLIT);
}
System.out.println(testType +" cost " + (System.currentTimeMillis() - start));
break;
case "stringUtils":
for (int i=0;i<MAX;i++) {
StringUtils.split(str,SPLIT);
}
System.out.println(testType +" cost " + (System.currentTimeMillis() - start));
break;
case "indexOf":
String tmp = str;
String splitStr = null;
for (int i=0;i<MAX;i++) {
while (true) {
int index = tmp.indexOf(SPLIT); // 找到分隔符
if (index < 0) {
break;
}
splitStr = tmp.substring(0,index); // 此次循环分隔的子串
tmp = tmp.substring(index+1); // 剩下需要处理的字符串
}
tmp = str;
}
System.out.println(testType +" cost " + (System.currentTimeMillis() - start));
break;
default:
break;
}
}

测试结果:

1
2
3
4
jdk cost 259
stringTokenizer cost 374
stringUtils cost 225
indexOf cost 149

有时候jdk>StringUtils,有时候反过来,差别很小。但StringTokenizer效率很低。indexOf始终是速度最快的。