java的可变类——StringBuffer

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进来的字符,放到数组后面;如果需要进行扩容,就会新生成一个大空间的数组。但是依旧返回的是同一个实例。

 

posted on 2015-06-08 15:38  飞机说之代码也疯狂  阅读(216)  评论(0编辑  收藏  举报