标签:
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 code 17 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) // overflow 27 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进来的字符,放到数组后面;如果需要进行扩容,就会新生成一个大空间的数组。但是依旧返回的是同一个实例。
标签:
原文地址:http://www.cnblogs.com/feijishuo/p/4561095.html