摘要
JDK:1.8.0_202
# 一:前言
下面分享几种常见的字符串切割方法,以及他们的耗时,
首先定义一个生成超长字符串的工具类,方便后面测试时使用
public class StringGeneratorUtils {
/**
* 生成一个用逗号分隔的超长字符串,从 0 开始一直到 9999 的每个数字都用逗号分隔
*
* @return 超长字符串
*/
public static String generate() {
StringBuilder stringBuffer = new StringBuilder();
int max = 10000;
for (int i = 0; i < max; i++) {
stringBuffer.append(i);
if (i < max - 1) {
stringBuffer.append(",");
}
}
return stringBuffer.toString();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
下面所有的例子中,因为单次切割时间太短,所以按照100次切割,作为一个单位时间,观察循环记录 50 次,可以看到他们的平均耗时。
同时由于真实的操作中,往往会对切割后,做一些其他操作,例如遍历,判断长度等等,为了更好模拟,下面的所有结果,都会打印第一个数字和最后一个数字。
# 二:String
使用最基础的split方法来对超长字符串做切割,如下代码测试:
public class StringSplitTest {
public static void main(String[] args) {
// 获取一个超长字符串
String string = StringGeneratorUtils.generate();
List<Long> list = new ArrayList<>(21);
for (int i = 1; i < 21; i++) {
System.out.printf("第%d次切割,\t", i);
list.add(extracted(string));
}
System.out.printf("平均耗时:%s", list.stream().mapToLong(Long::longValue).average().getAsDouble());
}
private static long extracted(String string) {
String[] strings = null;
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
// 切割字符串
strings = string.split(",");
}
System.out.printf("切割耗时:%d,", System.currentTimeMillis() - start);
System.out.printf("查找第一个数字:%s,查找最后一个数字:%s,", strings[0], strings[strings.length - 1]);
long allTime = System.currentTimeMillis() - start;
System.out.printf("总耗时:%d\n", allTime);
return allTime;
}
}
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
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
运行结果:
多运行几次,可以发现数值基本在 26ms ~ 28ms
之间波动
# 三:StringTokenizer
这个工具是 JDK 提供的,也是专门用来进行字符串切割的,如果不用 list 等记录,效果会很好,测试代码如下:
public class StringTokenizerSplitTest {
public static void main(String[] args) {
// 获取一个超长字符串
String string = StringGeneratorUtils.generate();
List<Long> list = new ArrayList<>(21);
for (int i = 0; i < 20; i++) {
System.out.printf("第%d次切割,\t", i);
list.add(extracted(string));
}
System.out.printf("平均耗时:%s", list.stream().mapToLong(Long::longValue).average().getAsDouble());
}
private static long extracted(String string) {
long start = System.currentTimeMillis();
StringTokenizer stringTokenizer = new StringTokenizer(string, ",");
List<String> list = new ArrayList<>(10_0001);
for (int i = 0; i < 100; i++) {
list.clear();
// 切割字符串
while (stringTokenizer.hasMoreTokens()) {
list.add(stringTokenizer.nextToken());
}
stringTokenizer = new StringTokenizer(string, ",");
}
System.out.printf("切割耗时:%d", System.currentTimeMillis() - start);
System.out.printf("查找第一个数字:%s,查找最后一个数字:%s,", list.get(0), list.get(list.size() - 1));
long allTime = System.currentTimeMillis() - start;
System.out.printf("总耗时:%d\n", allTime);
return allTime;
}
}
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
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
运行结果:
多运行几次,可以发现数值基本在 27ms ~ 30ms
之间波动,这里面的时间,有一部分消耗在了 list.add() 等操作上
# 四:Apache-commons
下面使用 apache commons工具包,里面的StringUtils工具类,进行切割测试
首先引入相关的依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
1
2
3
4
5
2
3
4
5
测试类如下:
import org.apache.commons.lang3.StringUtils;
public class ApacheTest {
public static void main(String[] args) {
// 获取一个超长字符串
String string = StringGeneratorUtils.generate();
List<Long> list = new ArrayList<>(21);
for (int i = 1; i < 21; i++) {
System.out.printf("第%d次切割,\t", i);
list.add(extracted(string));
}
System.out.printf("平均耗时:%s", list.stream().mapToLong(Long::longValue).average().getAsDouble());
}
private static long extracted(String string) {
String[] strings = null;
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
// 切割字符串
strings = StringUtils.split(string, ",");
}
System.out.printf("切割耗时:%d,", System.currentTimeMillis() - start);
System.out.printf("查找第一个数字:%s,查找最后一个数字:%s,", strings[0], strings[strings.length - 1]);
long allTime = System.currentTimeMillis() - start;
System.out.printf("总耗时:%d\n", allTime);
return allTime;
}
}
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
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
运行结果:
多运行几次,可以发现数值基本在 44ms ~ 48ms
之间波动
# 五:小结
其实总的来说,如果在项目中使用,基本单个切割的时间可以忽略不计。所以直接使用 String.split() 即可。如果遇到一边切割,一边直接处理,不用存储的话,可以考虑直接用 StringTokenizer。