關於Java字符串的拼接,你瞭解多少? 頂 原

關於Java字符串的拼接,你瞭解多少?

前景

昨晚開了一個review會,就在循環內部創建String對象的問題展開了激烈的討論。今早小夥伴們意猶未盡,就字符串的拼接又一次在羣裏炸開了鍋。作爲一個有幾年工作經驗的我來說,在這次的討論中受益匪淺。

代碼中常見的字符串拼接方式

用“+”拼接字符串

String ab = "a" + "b";

輸出 : ab

String.format()

String ab = String.format("%s%s","a","b");

輸出 : ab

StringBuilder和StringBuffer

StringBuilder sb = new StringBuilder()
sb.append(“a”);
sb.append(“b”);
String ab = sb.toString();

輸出 : ab

性能測試

網上對它們的性能普遍認爲“+號”性能較差。爲了看出效果,時間單位爲微秒,納秒有點太小了。

String a1 = "a";
String b1 = "b";
Thread.sleep(1000);
long start1 = System.nanoTime();
String ab1 = a1 + b1;
long end1 = System.nanoTime();
System.out.println("+號拼接 : " + ((end1 - start1) / 1000) + "ws");     


String a2 = "a";
String b2 = "b";
Thread.sleep(1000);
long start2 = System.nanoTime();
String ab2 = String.format("%s%s", a2, b2);
long end2 = System.nanoTime();
System.out.println("String.format() : " + ((end2 - start2) / 1000)+ "ws");      


String a3 = "a";
String b3 = "b";
Thread.sleep(1000);
long start3 = System.nanoTime();
StringBuilder sb = new StringBuilder();
sb.append(a3);
sb.append(b3);
String ab3 = sb.toString();
long end3 = System.nanoTime();
System.out.println("StringBuilder.append() : "+ ((end3 - start3) / 1000)+ "ws");


輸出 : 
+號拼接 : 127ws
String.format() : 46584ws
StringBuilder.append() : 62ws


你可以再試試5以內的字符串拼接。結果差不多。

結果

在2-5個數左右的字符串拼接中“+”號拼接和StringBuilder的耗時相差無幾,而String.format()耗時較多

分析

爲了進一步瞭解String,查看到了JDK1.6的源碼,String.class開頭註釋寫到

  • The Java language provides special support for the string
  • concatenation operator ( + ), and for conversion of
  • other objects to strings. String concatenation is implemented
  • through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
  • class and its <code>append</code> method.
  • String conversions are implemented through the method
  • <code>toString</code>, defined by <code>Object</code> and
  • inherited by all classes in Java. For additional information on
  • string concatenation and conversion, see Gosling, Joy, and Steele,
  • <i>The Java Language Specification</i>.

這段話的大致意思就是說

java語言提供了字符串串聯運算符,和其他對象轉換爲字符串,字符串連接是底層通過StringBuilder或者StringBuffer來實現的。

這下就明白了爲什麼“+”號拼接和StringBuilder拼接的耗時相差無幾了,但爲什麼String.format()的耗時相差甚遠呢?

public static String format(String format, Object ... args) {
	return new Formatter().format(format, args).toString();
}

public Formatter() {
	init(new StringBuilder(), Locale.getDefault());
}

在上述代碼中不難看出底層也是用StringBuilder實現的,這就不能理解了,同樣是StringBuilder,爲什麼相差那麼大呢?咱們接着往下看。

 private FormatString[] parse(String s) {
	ArrayList al = new ArrayList();
	Matcher m = fsPattern.matcher(s);
        ...
}

上述代碼是在new Formatter().format()方法中找到的,原來內部有正則匹配操作。衆所周知,正則匹配是很消費性能的。這下可以解開心中的迷惑了。

結論

  • 就可讀性和簡潔性而言,數量不多的拼接,“+”號拼接是個很不錯的字符串拼接方式。
  • String.format()還沒找到適合用他的場景。(也許是需要正則匹配,有的話請告訴我)
  • 循環中StringBuilder和StringBuffer性能更優。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章