String 、StringBuffer 與StringBuilder的異同詳解
在聲明方面:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
String、StringBuffer、StringBuilder都實作了CharSequence接口和Serializable接口 ;
String、StringBuffer、StringBuilder都是final不可繼承和重寫;
String實作了字元串比較的Comparable接口;
StringBuffer和StringBuilder都繼承AbstractStringBuilder抽象類;
在字元串拼接效率上:
String<StringBuffer<StringBuilder,但是如果是String str=“a”+“b”+“c“是效率最高的。因為”a“、”b“、”c“都在字元串常量池裡面。就是直接在常量池将a、b、c拼接成abc再放入字元串常量池。
如果沒有這三句指派String s1=”a”;String s2=”b”;String s3=”c”;
String str=“a”+“b”+“c“;這句語句會生成4個新對象均放入字元串常量池中
如圖:
測試如圖
public static void main(String[] args) {
StringBuilder strB = new StringBuilder();
// String str = new String();
String a1 = "1";
String b1 = "2";
String c1 = "3";
String d1 = "3";
String e1 = "3";
String f1 = "3";
String g1 = "3";
String h1 = "3";
String i1 = "3";
long startTime = System.nanoTime();
// strB.append(a1).append(b1).append(c1).append(d1).append(e1).append(f1).append(g1).append(h1).append(i1);
// strB.append(a1);strB.append(b1);strB.append(c1);strB.append(d1);
// strB.append(e1);strB.append(f1);strB.append(g1);strB.append(h1);strB.append(i1);
strB.append("a").append("b").append("c").append("d").append("e").append("f").append("g").append("h").append("i");
long endTime = System.nanoTime();
System.out.println(endTime-startTime);
long startTime1 = System.nanoTime();
// str +=a1;str +=b1;str +=c1;str +=d1;str +=e1;str +=f1;str +=g1;str +=h1;str +=i1;
// str = a1 + b1 + c1 + d1 + e1 + f1 + g1 + h1 + i1;
String str = "j"+"k"+"l"+"m"+"n"+"o"+"p"+"q"+"r";
long endTime1 = System.nanoTime();
System.out.println(endTime1-startTime1);
}
第一行是StringBuilder,第二行String。
顯然String的操作快很多。
而如果是類似下圖的String拼接(其實質是通過StringBuilder的append方法來拼接,但是每次都會傳回一個String對象,存放在堆中)。可以通過IDE的debug的Force step into調試看出來。
public static void main(String[] args) {
StringBuilder strB = new StringBuilder();
String str = new String();
String a1 = "1";
String b1 = "2";
String c1 = "3";
String d1 = "3";
String e1 = "3";
String f1 = "3";
String g1 = "3";
String h1 = "3";
String i1 = "3";
long startTime = System.nanoTime();
// strB.append(a1).append(b1).append(c1).append(d1).append(e1).append(f1).append(g1).append(h1).append(i1);
strB.append(a1);strB.append(b1);strB.append(c1);strB.append(d1);
strB.append(e1);strB.append(f1);strB.append(g1);strB.append(h1);strB.append(i1);
long endTime = System.nanoTime();
System.out.println(endTime-startTime);
long startTime1 = System.nanoTime();
str +=a1;str +=b1;str +=c1;str +=d1;str +=e1;str +=f1;str +=g1;str +=h1;str +=i1;
long endTime1 = System.nanoTime();
System.out.println(endTime1-startTime1);
}
第一行是StringBuilder,第二行String。
其主要是在字元串拼接過程中StringBuilder不會生成新的StringBuilder對象,而String每次都會生成新String對象放入堆記憶體中,雖然他們的拼接都是用StringBuilder的方法。
也是以,如果是如下圖的String的字元串拼接,就會發現如果兩者字元串拼接效率是相近的。
public static void main(String[] args) {
StringBuilder strB = new StringBuilder();
String str = new String();
String a1 = "1";
String b1 = "2";
String c1 = "3";
String d1 = "3";
String e1 = "3";
String f1 = "3";
String g1 = "3";
String h1 = "3";
String i1 = "3";
long startTime = System.nanoTime();
// strB.append(a1).append(b1).append(c1).append(d1).append(e1).append(f1).append(g1).append(h1).append(i1);
strB.append(a1);strB.append(b1);strB.append(c1);strB.append(d1);
strB.append(e1);strB.append(f1);strB.append(g1);strB.append(h1);strB.append(i1);
long endTime = System.nanoTime();
System.out.println(endTime-startTime);
long startTime1 = System.nanoTime();
// str +=a1;str +=b1;str +=c1;str +=d1;str +=e1;str +=f1;str +=g1;str +=h1;str +=i1;
str = a1 + b1 + c1 + d1 + e1 + f1 + g1 + h1 + i1;
long endTime1 = System.nanoTime();
System.out.println(endTime1-startTime1);
}
第一行是StringBuilder,第二行String。
StringBuilder的構造預設容量為16
public StringBuilder() {
super(16);
}
如下圖是StringBuilder的父類AbstractStringBuilder裡面的的擴容方法,
把 (長度)×2+2;
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
StringBuffer與StringBuilder差不多,因為StringBuffer也是繼承抽象類
AbstractStringBuilder,是以StringBuffer在與String類型字元串拼接效率上比較也是比String類型的要快。其次就是跟StringBuilder比較主要是StringBuffer的大多數方法加了syncronized關鍵字,也是以StringBuffer是線程安全的,StringBuilder是非線程安全的。
public static void main(String[] args) {
String a1 = "1";
String b1 = "2";
String c1 = "2";
String d1 = "3";
String e1 = "3";
String f1 = "3";
String g1 = "3";
String h1 = "3";
String i1 = "3";
StringBuilder sbd = new StringBuilder();
StringBuffer sb = new StringBuffer();
long startTime = System.nanoTime();
sbd.append(a1);sbd.append(b1);sbd.append(c1);sbd.append(d1);
sbd.append(e1);sbd.append(f1);sbd.append(g1);sbd.append(h1);sbd.append(i1);
long endTime = System.nanoTime();
System.out.println(endTime - startTime);
long startTime1 = System.nanoTime();
sb.append(a1);sb.append(b1);sb.append(c1);sb.append(d1);
sb.append(e1);sb.append(f1);sb.append(g1);sb.append(h1);sb.append(i1);
long endTime1 = System.nanoTime();
System.out.println(endTime1 - startTime1);
}
第一行是StringBuilder的,第二行是Stringbuffer的
發現其實差不多,是以線程安全的情況下用StringBuilder,非線程安全用StringBuffer。主要還是具體情況具體分析。