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%