標籤:
StringBuffer是一個安全執行緒的類。看這個類是否是安全執行緒的,就是看這個類提供的對成員變數進行操作的方法是否是同步的。
我們經常會拿StringBuffer和String進行比較,當我們進行字串的拼接操作時,都會選擇StringBuffer的append方法,之所以如此,就是認為,append方法拼接字串的
效率會比較高。原因就是append方法是在原字串的後面進行添加操作,不會像String一樣,改變其值就是另外開闢一個空間。
通過證明,append的操作確實比“+”來的高效。
1 public static void main(String[]args) { 2 String str=""; 3 long start0=System.currentTimeMillis(); 4 for(int i=0;i<10000;i++) { 5 str+="feijishuo"; 6 } 7 long end0=System.currentTimeMillis(); 8 System.out.println((end0-start0)+"ms"); 9 10 StringBuffer sb=new StringBuffer();11 long start1=System.currentTimeMillis();12 for(int i=0;i<10000;i++) {13 sb.append("feijishuo");14 }15 long end1=System.currentTimeMillis();16 System.out.println((end1-start1)+"ms");17 }
563ms
1ms
當拼接的字串越多時,這種差距越明顯。
StringBuffer的屬性類型為char[] value,是可變性參數,因此可以對其本身執行個體做修改後將這個執行個體返回。
細想一下,既然StringBuffer的底層是數群組類型,而數組是固定長度的,要實現擴容只有新new出來一個數組,然後將其拷貝內容拷貝到這個
新數組,後又將append進來的字元拷貝到這個新數組的後面。
1 public synchronized StringBuffer append(String str) { 2 super.append(str); 3 return this; 4 } 5 6 public AbstractStringBuilder append(String str) { 7 if (str == null) str = "null"; 8 int len = str.length(); 9 ensureCapacityInternal(count + len);10 str.getChars(0, len, value, count);11 count += len;12 return this;13 }14 15 private void ensureCapacityInternal(int minimumCapacity) {16 // overflow-conscious code17 if (minimumCapacity - value.length > 0)18 expandCapacity(minimumCapacity);19 }20 21 void expandCapacity(int minimumCapacity) {22 int newCapacity = value.length * 2 + 2;23 if (newCapacity - minimumCapacity < 0)24 newCapacity = minimumCapacity;25 if (newCapacity < 0) {26 if (minimumCapacity < 0) // overflow27 throw new OutOfMemoryError();28 newCapacity = Integer.MAX_VALUE;29 }30 value = Arrays.copyOf(value, newCapacity);31 }32 33 public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {34 if (srcBegin < 0) {35 throw new StringIndexOutOfBoundsException(srcBegin);36 }37 if (srcEnd > value.length) {38 throw new StringIndexOutOfBoundsException(srcEnd);39 }40 if (srcBegin > srcEnd) {41 throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);42 }43 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);44 }
程式碼分析:
StringBuffer如果不需要進行擴容,就會直接將append進來的字元,放到數組後面;如果需要進行擴容,就會新產生一個大空間的數組。但是依舊返回的是同一個執行個體。
java的可變類——StringBuffer