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()方法好了!也許這就是你的程序的性能瓶頸!