出于方便的考虑,我们在进行字符串的内容处理的时候往往会出现以下的代码:
String result=""; result+="ok"; | 这段代码看上去好像没有什么问题,但是需要指出的是其性能很低,原因是java中的String类不可变的(immutable),这段代码实际的工作过程会是如何的呢?通过使用javap工具我们可以知道其实上面的代码在编译成字节码的时候等同的源代码是:
String result=""; StringBuffer temp=new StringBuffer(); temp.append(result); temp.append("ok"); result=temp.toString(); | 短短的两个语句怎么呢变成这么多呢?问题的原因就在String类的不可变性上,而java程序为了方便简单的字符串使用方式对+操作符进行了重载,而这个重载的处理可能因此误导很多对java中String的使用。 下面给出一个完整的代码:
public class Perf { public static String detab1(String s) { if (s.indexOf('\t') == -1) return s; String res = ""; int len = s.length(); int pos = 0; int i = 0; for (; i < len && s.charAt(i) == '\t'; i++) { res += " "; pos += 8; } for (; i < len; i++) { char c = s.charAt(i); if (c == '\t') { do { res += " "; pos++; } while (pos % 8 != 0); } else { res += c; pos++; } } return res; }
public static String detab2(String s) { if (s.indexOf('\t') == -1) return s; StringBuffer sb = new StringBuffer(); int len = s.length(); int pos = 0; int i = 0; for (; i < len && s.charAt(i) == '\t'; i++) { sb.append(" "); pos += 8; } for (; i < len; i++) { char c = s.charAt(i); if (c == '\t') { do { sb.append(' '); pos++; } while (pos % 8 != 0); } else { sb.append(c); pos++; } } return sb.toString(); }
public static String testlist[] = { "", "\t", "\t\t\tabc", "abc\tdef", "1234567\t8", "12345678\t9", "123456789\t" };
public static void main(String args[]) { for (int i = 0; i < testlist.length; i++) { String tc = testlist[i]; if (!detab1(tc).equals(detab2(tc))) System.err.println(tc); }
String test_string = "\t\tthis is a test\tof detabbing performance"; int N = 5000; int i = 0;
long ct = System.currentTimeMillis(); for (i = 1; i <= N; i++) detab1(test_string); long elapsed = System.currentTimeMillis() - ct; System.out.println("String time = " + elapsed);
ct = System.currentTimeMillis(); for (i = 1; i <= N; i++) detab2(test_string); elapsed = System.currentTimeMillis() - ct; System.out.println("StringBuffer time = " + elapsed); } } |
执行以上代码的结果可以看到使用StringBuffer的版本的方法比使用String版本的一般都快十倍以上(本人使用的是JDK1.4.0),你可以执行一下看看结果到底如何。
因此得到的结论是:如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法好了!也许这就是你的程序的性能瓶颈! |