String、StringBuiler、StringBuffer,誰性能最高?

Java技術棧
www.javastack.cn
關注閱讀更多優(yōu)質(zhì)文章
作者:Yuchao Huang
來源:www.cnblogs.com/misterchaos/p/12782986.html
一、前言
剛開始學習Java時,作為只會C語言的小白,就為其中的字符串操作而感到震撼。
相比之下,C語言在字節(jié)數(shù)組中保存一個結尾的\0去表示字符串,想實現(xiàn)字符串拼接,還需要調(diào)用strcpy庫函數(shù)或者自己手動去復制數(shù)組,非常麻煩,更別提其他復雜操作。
而Java通過String類讓字符串操作變得十分簡單和方便。除此之外,還有stringbuilder等這些類的輔助,那么本文就從String,StringBuiler和StringBuffer的區(qū)別開始,去探討Java中的字符串操作。
二、String,StringBuiler和StringBuffer
2.1 String類
Java 提供了 String 類來創(chuàng)建和操作字符串。關注公眾號Java技術棧回復面試獲取系列面試題。
在源碼中可以看到,String類內(nèi)部的實現(xiàn)也是一個字節(jié)數(shù)組,這個數(shù)組是final類型的,因此String是不可變的對象,每次在對String類進行改變的時候都會生成一個新的string對象,然后將指針指向新的string對象。
推薦閱讀《5 個刁鉆的 String 面試題!》
2.2 StringBuiler 類
和 String 類不同的是,StringBuilder 類的對象能夠被多次的修改,并且不產(chǎn)生新的對象。
這個特性的意義在于,如果我們進行大量的字符串操作,使用String類就會產(chǎn)生很大的性能消耗,而StringBuilder就可以避免這個問題。
2.3 StringBuffer 類
StringBuffer 和StringBuiler之間的最大不同在于 StringBuilder 的方法不是線程安全的。
2.4 String,StringBuiler和StringBuffer的比較(對比C/C++)

三、各種字符串操作的效率測試
3.1 測試代碼
@Test
public?void?test()?{
????int?count?=?100000;
????long?startTime?=?System.currentTimeMillis();
????String?str?=?"";
????for(int?i?=?0;?i????????str?+=?i;
????}
????System.out.println("執(zhí)行"+count+"次??String?耗時:"+?getRunTime(startTime));
????startTime?=?System.currentTimeMillis();
????StringBuilder?stringBuilder?=?new?StringBuilder("");
????for?(int?i?=?0;?i?????????stringBuilder.append(i);
????}
????System.out.println("執(zhí)行"+count+"次??StringBuilder?耗時:"+?getRunTime(startTime));
????startTime?=?System.currentTimeMillis();
????StringBuffer?stringBuffer?=?new?StringBuffer("");
????for?(int?i?=?0;?i?????????stringBuffer.append(i);
????}
????System.out.println("執(zhí)行"+count+"次??StringBuffer?耗時:"+?getRunTime(startTime));
}
3.2 測試結果
執(zhí)行100000次??String?耗時:32s
執(zhí)行100000次??StringBuilder?耗時:2ms
執(zhí)行100000次??StringBuffer?耗時:4ms
3.3 小結
可以看到String類的性能遠低于StringBuiler和StringBuffer,而StringBuiler在本次測試中比Stringbuffer提高了50%的性能
四、Java字符串和正則表達式
4.1 測試代碼
@Test
public?void?test0(){
????//郵政編碼
????String?postCode?=?"[1-9]\\d{5}";
????//區(qū)號-座機號碼
????String?areaCode?=?"\\d{3}-\\d{8}|\\d{4}-\\d{7}";
????//手機號碼
????String?phone?=?"(?:13\\d|15\\d|18\\d)\\d{5}(\\d{3}|\\*{3})";
????String?text?=?"郵政編碼:440834"+
??????????????????"區(qū)號-座機號碼:?020-12345678"+
??????????????????"手機號:13536373839"+
??????????????????"郵政編碼:440833"+
??????????????????"區(qū)號-座機號碼:?010-12345678"+
??????????????????"手機號:13536373739";
????Pattern?p?=?Pattern.compile(postCode);
????Matcher?m?=?p.matcher(text);
????System.out.println("文本中包含郵政編碼:");
????while?(m.find()){
????????System.out.println(m.group());
????}
????p?=?Pattern.compile(areaCode);
????m=?p.matcher(text);
????System.out.println("文本中包含區(qū)號-座機號碼:");
????while?(m.find()){
????????System.out.println(m.group());
????}
????p?=?Pattern.compile(phone);
????m=?p.matcher(text);
????System.out.println("文本中包含手機號:");
????while?(m.find()){
????????System.out.println(m.group());
????}
}
4.2 測試結果
文本中包含郵政編碼:
440834
123456
135363
440833
123456
135363
文本中包含區(qū)號-座機號碼:
020-12345678
010-12345678
文本中包含手機號:
13536373839
13536373739
五、總結
經(jīng)過測試和比較,可以看到Java中同為字符串操作,但由于背后實現(xiàn)的原理不同,形成的性能差異也是十分巨大,相比之下,C/C++中的字符串操作性能更高。
String類的性能遠低于StringBuiler和StringBuffer,而StringBuiler比Stringbuffer的性能稍微高一點。對性能的探究,最終還是要回到使用場景。
可以總結得出,如果不涉及字符串操作,那么String類是首選,如果涉及的字符串操作沒有線程安全問題,那么使用StringBuilder,如果涉及的字符串操作存在線程安全問題,那么使用StringBuffer






關注Java技術棧看更多干貨
戳原文,獲取精選面試題!
