最近腾出时间来了,将1年前学习的一些东西整理出来
String、StringBuffer与StringBuilder这三个类用在字符串处理中,那么他们到底有什么优、缺点,什么时候该用谁呢?下面我们从以下几点说明一下
1.三者在平均效率方面的比较:StringBuilder > StringBuffer > String
String:字符串常量,只能被创建或销毁。
StringBuffer:字符串变量,通过append()/insert()...方法修改。
StringBuilder:字符串变量,通过append()/insert()...方法修改。
String str = "ASDFG";
str += 3;
System.out.println(str);
结果是
ASDFG3
我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 这牵涉到jvm中的处理了。
JVM是这样解析这段代码的:先创建对象str,赋予初始值为ASDFG,然后在另一块内存中创建一个新的对象用来存放执行str += 3后的结果;
也就是说我们之前对象str中的内容并没有变化还是ASDFG,所以我们说String类型是不可改变的对象了,
由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会很低。
StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,
不像String那样每次都会创建一些对象进行操作,所以速度就快多了。
2、特殊情况下的比较
String str3 = "a" + "b" + "c" + "d";
对于上面的例子,jvm会进行优化,将字符串"a"、“b”、“c”、“d”进行优化为一个字符串"abcd",只是创建了一个对象。
对于下面的例子:
String str3 = "a" + "b" + "c" + "d";
String str = "ASDFG";
String str2 = str + str3;
jvm会按照原来的方式创建字符串"abcd"和创建字符串"ASDFG",最后创建“abcdASDFG”,这样就会导致执行速度很慢。
3、线程安全性
StringBuilder:线程非安全的
StringBuffer:线程安全的
String:不确定,没有研究过
从他们对应的源码中分析可知:
StringBuffer:
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
......
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
......
}
StringBuffer继承了AbstractStringBuilder,AbstractStringBuilder的源代码如下:
abstract class AbstractStringBuilder implements Appendable, CharSequence {
......
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
if (len == 0) return this;
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
str.getChars(0, len, value, count);
count = newCount;
return this;
}
......
}
可以看到StringBuffer重写了父类方法,
在父类方法的基础上增加了同步,所以会消耗一定的性能
(
StringBuffer的很多方法都是同步方法
)
StringBuilder:
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
......
public StringBuilder append(String str) {
super.append(str);
return this;
}
......
}
可以看到 StringBuilder没有对方法进行同步,所以效率会高不少 ( StringBuilder没有同步方法 ),是线程不安全的。
对于三者使用的总结: 1.如果要操作少量的数据并且频率不高的情况用 : String
2.单线程操作字符串缓冲区下操作大量数据 : StringBuilder
3.多线程操作字符串缓冲区时操作大量数据 : StringBuffer