Java中的String、StringBuilder、StringBuffrer

String
String就是字符串,Java中的字符串是Immutable(不可变的)。如:

String before = "before";
String after = before.replace('b', 'e');
// before => "before", after => "eefore"

因为String本身是immutable的,所以,String本身必然是thread safe(线程安全)的。


StringBuilder
StringBuilder是在JDK1.5以后引入的,用来构建和修改字符串。StringBuilder它提供了如append、insert这样的方法用来修改原始的字符串。与String不同,StringBuilder不是thread safe的。
一般来说当涉及到字符串的修改、拼接时,StringBuilder的运行效率会比String本身会高,我们就用实验来说明:
实验一
【Java中的String、StringBuilder、StringBuffrer】a) 当LIMIT等于100000时,
String res = "";
for (int i = 0; i < LIMIT; i++) {
res += i + ",";
}

这段代码执行时间10.556秒
b) 当LIMIT等于100000时,
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < LIMIT; i++) {
stringBuilder.append(i);
stringBuilder.append(",");
}

这段代码仅仅用了0.007秒
由此对比,可见效率相差甚多。


于是,有人可能会问,既然这样,我们所有的涉及到构建字符串的行为都应该用StringBuilder来做呢?
其实不然,我们将刚才的例子稍作修改。


实验二
a) 当LIMIT等于100000时,
for (int i = 0; i < LIMIT; i++) {
String res = i + ",";
}

这段代码执行时间0.007秒
b) 当LIMIT等于100000时,

for (int i = 0; i < LIMIT; i++) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(i);
stringBuilder.append(",");
}

这段代码执行时间0.010秒
两者相差无几。但是第一种方式还会更简单,更容易理解。所以,这样的情况下直接使用String自身的方法用作构建字符串应该是更好的选择。


原因分析:当我们写出类似a + b + c这样的方式连接三个字符串时,其本身的行为就是构建一个StringBuilder,然后使用StringBuilder的append功能将这三个字符串进行拼接,最后再调用toString方法转换为字符串。(参考http://chaoticjava.com/posts/stringbuilder-vs-string/)所以,在实验一a)较实验一b)不用每次都去构建StringBuilder,也不会在每次都去调用toString方法。所以,在这样的情况下使用StringBuffer会比直接使用String快很多。而在实验二a)和实验二b)中,两者几乎等价。所以,效率差不多。




StringBuffer
StringBuffer从JDK1.0就有了,StringBuffer与StringBuilder都继承于AbstractStringBuilder。在构造字符串的角度来说,两者完全一样。但是StringBuffer是thread safe,这就是他们仅有的区别。


参考资料:
http://www.examiner.com/article/when-to-use-the-java-string-stringbuffer-and-stringbuilder-classes
http://blog.vogella.com/2009/07/19/java-string-performanc/
http://chaoticjava.com/posts/stringbuilder-vs-string/

    推荐阅读