StringBuffer和StringBuilder区别?

1. String是不可变类,改变String变量中的值,相当于开辟了新的空间存放新的string变量

2. StringBuffer 可变的类,可以通过append方法改变变量的值,且StringBuffer是线程安全的,它的很多方法都是同步方法,支持并发操作,适用于多线程    

3. StringBuilder 可变的类,但是线程不安全的,用于单线程中性能高于StringBuffer

4. HashTable 线程安全的,HashMap线程不安全的

为什么StringBuffer是同步的?

因为很多方法都是synchronized 。。。

  1 /*
  2  * @(#)StringBuffer.java    1.101 05/11/17
  3  *
  4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6  */
  7 
  8 package java.lang;
  9 
 10 
 11 /**
 12  * A thread-safe, mutable sequence of characters. 
 13  * A string buffer is like a {@link String}, but can be modified. At any 
 14  * point in time it contains some particular sequence of characters, but 
 15  * the length and content of the sequence can be changed through certain 
 16  * method calls.
 17  * <p>
 18  * String buffers are safe for use by multiple threads. The methods 
 19  * are synchronized where necessary so that all the operations on any 
 20  * particular instance behave as if they occur in some serial order 
 21  * that is consistent with the order of the method calls made by each of 
 22  * the individual threads involved.
 23  * <p>
 24  * The principal operations on a <code>StringBuffer</code> are the 
 25  * <code>append</code> and <code>insert</code> methods, which are 
 26  * overloaded so as to accept data of any type. Each effectively 
 27  * converts a given datum to a string and then appends or inserts the 
 28  * characters of that string to the string buffer. The 
 29  * <code>append</code> method always adds these characters at the end 
 30  * of the buffer; the <code>insert</code> method adds the characters at 
 31  * a specified point. 
 32  * <p>
 33  * For example, if <code>z</code> refers to a string buffer object 
 34  * whose current contents are "<code>start</code>", then 
 35  * the method call <code>z.append("le")</code> would cause the string 
 36  * buffer to contain "<code>startle</code>", whereas 
 37  * <code>z.insert(4, "le")</code> would alter the string buffer to 
 38  * contain "<code>starlet</code>". 
 39  * <p>
 40  * In general, if sb refers to an instance of a <code>StringBuffer</code>, 
 41  * then <code>sb.append(x)</code> has the same effect as 
 42  * <code>sb.insert(sb.length(), x)</code>.
 43  * <p>
 44  * Whenever an operation occurs involving a source sequence (such as
 45  * appending or inserting from a source sequence) this class synchronizes
 46  * only on the string buffer performing the operation, not on the source.
 47  * <p>
 48  * Every string buffer has a capacity. As long as the length of the 
 49  * character sequence contained in the string buffer does not exceed 
 50  * the capacity, it is not necessary to allocate a new internal 
 51  * buffer array. If the internal buffer overflows, it is 
 52  * automatically made larger. 
 53  *
 54  * As of  release JDK 5, this class has been supplemented with an equivalent 
 55  * class designed for use by a single thread, {@link StringBuilder}.  The 
 56  * <tt>StringBuilder</tt> class should generally be used in preference to 
 57  * this one, as it supports all of the same operations but it is faster, as 
 58  * it performs no synchronization.
 59  *
 60  * @author    Arthur van Hoff
 61  * @version     1.101, 11/17/05
 62  * @see     java.lang.StringBuilder
 63  * @see     java.lang.String
 64  * @since   JDK1.0
 65  */
 66  public final class StringBuffer
 67     extends AbstractStringBuilder
 68     implements java.io.Serializable, CharSequence
 69 {
 70 
 71     /** use serialVersionUID from JDK 1.0.2 for interoperability */
 72     static final long serialVersionUID = 3388685877147921107L;
 73 
 74     /**
 75      * Constructs a string buffer with no characters in it and an 
 76      * initial capacity of 16 characters. 
 77      */
 78     public StringBuffer() {
 79     super(16);
 80     }
 81 
 82     /**
 83      * Constructs a string buffer with no characters in it and 
 84      * the specified initial capacity. 
 85      *
 86      * @param      capacity  the initial capacity.
 87      * @exception  NegativeArraySizeException  if the <code>capacity</code>
 88      *               argument is less than <code>0</code>.
 89      */
 90     public StringBuffer(int capacity) {
 91     super(capacity);
 92     }
 93 
 94     /**
 95      * Constructs a string buffer initialized to the contents of the 
 96      * specified string. The initial capacity of the string buffer is 
 97      * <code>16</code> plus the length of the string argument.
 98      *
 99      * @param   str   the initial contents of the buffer.
100      * @exception NullPointerException if <code>str</code> is <code>null</code>
101      */
102     public StringBuffer(String str) {
103     super(str.length() + 16);
104     append(str);
105     }
106 
107     /**
108      * Constructs a string buffer that contains the same characters
109      * as the specified <code>CharSequence</code>. The initial capacity of
110      * the string buffer is <code>16</code> plus the length of the
111      * <code>CharSequence</code> argument.
112      * <p>
113      * If the length of the specified <code>CharSequence</code> is
114      * less than or equal to zero, then an empty buffer of capacity
115      * <code>16</code> is returned.
116      *
117      * @param      seq   the sequence to copy.
118      * @exception NullPointerException if <code>seq</code> is <code>null</code>
119      * @since 1.5
120      */
121     public StringBuffer(CharSequence seq) {
122         this(seq.length() + 16);
123         append(seq);
124     }
125 
126     public synchronized int length() {
127     return count;
128     }
129 
130     public synchronized int capacity() {
131     return value.length;
132     }
133 
134 
135     ...

既然StringBuffer是线程同步的,那么代价就是损失性能,摘自一个测试http://blog.sina.com.cn/s/blog_5749ead90100b7lq.html

public class TestBufferAndBuilder {
 public static void main(String[] args) {

  String randoms[] = { String.valueOf(Math.random()), String.valueOf(Math.random()), String.valueOf(Math.random()), String.valueOf(Math.random()),
    String.valueOf(Math.random()), String.valueOf(Math.random()), String.valueOf(Math.random()), String.valueOf(Math.random()), String.valueOf(Math.random()),
    String.valueOf(Math.random()) };

  System.gc();
  long d = System.currentTimeMillis();
  for (int i = 0; i < 1000000; i++) {
   StringBuffer buffer = new StringBuffer();
   buffer.append(randoms[0]).append(randoms[1]).append(randoms[2]).append(randoms[3]).append(randoms[4]).append(randoms[5]).append(randoms[6]).append(randoms[7]).append(
     randoms[8]).append(randoms[9]);
  }
  System.err.println(System.currentTimeMillis() - d);
  System.gc();

  d = System.currentTimeMillis();
  for (int i = 0; i < 1000000; i++) {
   StringBuilder builder = new StringBuilder();
   builder.append(randoms[0]).append(randoms[1]).append(randoms[2]).append(randoms[3]).append(randoms[4]).append(randoms[5]).append(randoms[6]).append(randoms[7]).append(
     randoms[8]).append(randoms[9]);
  }
  System.err.println(System.currentTimeMillis() - d);

  System.gc();
  d = System.currentTimeMillis();
  for (int i = 0; i < 1000000; i++) {
   StringBuffer buffer = new StringBuffer(200);
   buffer.append(randoms[0]).append(randoms[1]).append(randoms[2]).append(randoms[3]).append(randoms[4]).append(randoms[5]).append(randoms[6]).append(randoms[7]).append(
     randoms[8]).append(randoms[9]);
  }
  System.err.println(System.currentTimeMillis() - d);
  System.gc();

  d = System.currentTimeMillis();
  for (int i = 0; i < 1000000; i++) {
   StringBuilder builder = new StringBuilder(200);
   builder.append(randoms[0]).append(randoms[1]).append(randoms[2]).append(randoms[3]).append(randoms[4]).append(randoms[5]).append(randoms[6]).append(randoms[7]).append(
     randoms[8]).append(randoms[9]);
  }
  System.err.println(System.currentTimeMillis() - d);

 }
}

输出结果:

    3188
    3657
    1672
    1859

结果如上,基本上要慢10-20%

posted @ 2018-04-04 16:37  进步青年!  阅读(272)  评论(0编辑  收藏  举报