说明:本文是阅读《Java程序性能优化》(作者:葛一明)一书中关于字符串分割与查找一节的笔记。
一、字符串分割
1、采用split方法分割字符串
如下代码所示,对原始字符串进行了10000次分割,在我的机器上用时大概3000ms左右。所以采用split方法对字符串进行分割虽然简单、功能强大,但是在性能敏感的系统中频繁使用时性能是非常不好的。
public class SplitDemo {
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(";");
}
str = sb.toString();
long begin = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
str.split(";");
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
}
}
2、使用效率更高的StringTokenizer类分割字符串
该类是JDK中提供的专门用来进行字符串分割的工具类。采用该类来进行上例中同样功能的字符串分隔如下,在我的机器上用时大概1800ms左右,即使在这段代码中StringTokenizer对象不断的被创建并销毁,其效率也高于采用split方法来分割字符串。
public class StringTokenizerDemo {
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(";");
}
str = sb.toString();
long begin = System.currentTimeMillis();
StringTokenizer st = new StringTokenizer(str, ";");
for (int i = 0; i < 10000; i ++) {
while (st.hasMoreTokens()) {
st.nextToken();
}
st = new StringTokenizer(str, ";");
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
}
}
3、更优化的字符串分割方式
可以自己设计算法来完成高效的字符串分割,如下代码所示,这里采用了JDK提供的String类的indexOf方法与substring方法,在“Java substring方法与内存溢出”一节中我们知道substring方法采用了空间换取时间的技术,所以它的执行速度相对会很快,只要处理好内存溢出的问题即可;而indexOf也是一个执行非常快的方法。以下代码完成了上例同样的功能,在我的机器上仅仅用了大概600ms左右的时间完成了10000次分割,远远超过了使用split方法或者StringTokenizer类的字符串分割,但是这种方式的代码可读性和系统的可维护性也是最差的。
public class CustomerSplitDemo {
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(";");
}
str = sb.toString();
long begin = System.currentTimeMillis();
String temp = str;
for (int i = 0; i < 10000; i++) {
while (true) {
String splitStr = null; // 保留截取的字符串
int index = temp.indexOf(";");
if (index < 0) {
break;
}
splitStr = temp.substring(0, index);
temp = temp.substring(index + 1);
}
temp = str;
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
}
}
二、高效的charAt方法
1、charAt方法与indexOf方法在效率上都是很高的方法。如下代码所示,判断10000000次字符串的开头与结尾是否是“abc”,单纯的使用charAt方法来实现,在我的机器上仅仅需要大概60ms左右的时间即可完成。
public class CharAtDemo {
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(";");
}
str = sb.toString();
long begin = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
int len = str.length();
if (str.charAt(0) == 'a' && str.charAt(1) == 'b' && str.charAt(2) == 'c');
if (str.charAt(len - 3) == 'a' && str.charAt(len - 2) == 'b' && str.charAt(len - 1) == 'c');
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
}
}
而使用JDK提供的startsWith与endsWith方法完成同样次数的同样的功能在我的机器上需要大概200ms左右的时间。