说明:本文是阅读《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左右的时间。