String、StringBuffer、StringBuilder的区别
String与StringBuffer&StringBuilder的区别:
相同点:
三者都是处理字符串常用的类,同时,都是被final修饰的类,不允许被继承
不同点:
1. 是否可变长
String底层是一个final修饰的字符数组,因此是不可变长的
public final class String implements
java.io.Serializable,
Comparable<String>,
CharSequence {
/** The value is used for character storage. */
private final char value[];
//...
}
而StringBuffer&StringBuilder都继承了AbstractStringBuilder,底层是可变长字符数组
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//...
}
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//...
}
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
//...
}
2. 实现的接口
String实现了java.io.Serializable, Comparable, CharSequence三个接口
而StringBuffer&StringBuilder只实现了Serializable、CharSequence两个接口
因此String的实例可以通过compareTo方法进行比较,而StringBuffer&StringBuilder不可以
但是StringBuffer&StringBuilder可以通过append、insert等方法对字符串进行操作,而String不可以
3. 执行速度
因为String是不可变长的字符数组,所以String的实例都是字符串常量(即String对象不可更改),而StringBuffer&StringBuilder的实例是字符串变量(对象可更改)。
因此从执行速度上看:StringBuffer&StringBuilder > String
应用场景:
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
StringBuffer与StringBuilder的区别:
相同点:
都继成了AbstractStringBuilder这个抽象父类,实现了CharSequence接口
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//...
}
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
//...
}
append方法
都是super.append(str),调用了父类AbstractStringBuilder的append(String str)方法
初始容量和扩容机制
初始容量都是16和扩容机制都是"旧容量*2+2"
初始容量:
public StringBuffer() {
super(16);
}
public StringBuider() {
super(16);
}
扩容:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len); //扩容
str.getChars(0, len, value, count);
count += len;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,newCapacity(minimumCapacity));
}
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2; // length*2 + 2
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
底层数组
都是用char[]字符数组实现,且都是可变的,与String不同
不同点:
1. 提出时间
StringBuffer从JDK1.0就有了,而StringBuilder类是JDK1.5才提出的
2. 线程安全
StringBuffer多线程安全的,因为它相关方法都加了synchronized 关键字
StringBuilder多线程不安全
3. 速度
因为StringBuffer需要获取锁和释放锁,而所以在单线程情况下,StringBuilder性能优于StringBuffer
4. toStringCache
StringBuffer比StringBuilder多一个字段:toStringCache,用来在toString方法中进行缓存,每次append操作之前都先将toStringCache设置为null,若连续多次调用toString方法,可避免每次Arrays.copyOfRange(value, 0, count)操作,节省性能。
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
应用场景:
StringBuffer虽然是多线程安全的,但是加了synchronized,导致其效率低下。故适用于多线程下,并发量不高的场景。
StringBuilder没有加任何锁,效率高,适用于单线程场景,但同时也适用于高并发场景中,提高高并发场景下的程序响应性能,通过ThreadLocal、CAS操作等方式解决其线程安全问题。
高并发场景下,优先使用StringBuilder