第一:运行速度不同(String<StringBuffer<StringBuilder)
第二:类型本质不同(String:字符串常量;StringBuffer和StringBuilder:字符串变量)
第三:StringBuffer和StringBuilder线程(StringBuffer线程安全,其大部分的方法都使用synchronized,适合多线程机制;StringBuilder线程不安全,适合单线程机制)
String:根据源码知道,定义String类是用final的,所以其是不可改变的,即为常量,有些人会困惑以下代码:
1 String s = "abcd";
2 s = s+1;
3 System.out.print(s);// result : abcd1
以上代码中,我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多低。
StringBuffer和StringBuilder都集成了AbstractStringBuilder,而StringBuffer大部分方法都是synchronized,也就是线程安全的,而StringBuilder就没有,所以,我们查看API可以知道,StringBuilder可以操作StringBuffer,但是StringBuffer不可以操作StringBuilder,这也是线程的原因;所以,可想而知,StringBuffer的效率肯定没有StringBuilder,因为StringBuffer要维持同步锁,这肯定要消耗部分资源。以下代码证明三者之间的区别:
package com.seven.exercise.StringTest;
import org.junit.Test;
public class StringBufferWithStringBuilder {
public void testString() {
long start = System.currentTimeMillis();
String str = null;
for (int i = 0; i < 20000; i++) {
str = str + i + ",";
}
System.out.println(System.currentTimeMillis() - start);
}
public void testStringBuffer() {
long start = System.currentTimeMillis();
StringBuffer sbuf = new StringBuffer();
for (int i = 0; i < 20000; i++) {
sbuf.append(i + ",");
}
System.out.println(System.currentTimeMillis() - start);
}
public void testStringBulider() {
long start = System.currentTimeMillis();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 20000; i++) {
builder.append(i + ",");
}
System.out.println(System.currentTimeMillis() - start);
}
@Test
public void test(){
testString();
testStringBuffer();
testStringBulider();
}
}
运行结果如下:
1217 9 6
- String适合处理少量数据,常量
- StringBuilder适合处理单线程大量数据
- StringBuffer适合处理多线程大量数据