StringBuffer和StringBulider
StringBuffer
String的值是不可修改的,这就导致每次对String的操作都会生成新的String对象(如果之前有的话会修改引用),不仅效率低下,而且浪费了大量内存空间。
//使用final关键字修饰的数组,不能修改
private final byte[] value;
String底层是用数组来存值的,数组长度一旦创建就不可在修改,所以不能再原有的对象基础上在进行修改。
1.StringBuffer
使用StringBuffer可以有效解决String频繁修改造成的空间资源浪费的问题。StringBuffer底层也是用数组来存值,但是StringBuffer数组有以下特点:
StringBuffer底层数组的默认长度为16,使用无参构造函数来创建对象。
@HotSpotIntrinsicCandidate
public StringBuffer() {
super(16);
}
StringBuffer使用有参构造来创建对象,底层数组长度=参数长度+16。
public StringBuffer(String str) {
super(str.length() + 16);
//追加
append(str);
}
注:length()
方法返回的不是底层数组的长度,而是它的有效长度(值的长度)。
如果StringBuffer一旦创建,默认会有16个字节的空间去修改。一旦追加的字符串长度超过16,StringBuffer不会重新开辟一块新的内存区域,而是使用ensureCapacity()
方法调用父类的ensureCapacityInternal()
方法在原有的基础上对底层数组进行扩容,引用没有改变。
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
if (minimumCapacity - oldCapacity > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity) << coder);
}
}
2.StringBuffer常见方法
方法 | 描述 |
---|---|
public StringBuffer() | 创建一个空的StringBuffer对象 |
public StringBuffer(String str) | 创建一个值为str的StringBuffer对象 |
public synchronized int length() | 返回StringBuffer对象的长度 |
public synchronized char charAt(int index) | 返回指定位置的字符 |
public synchronized StringBuffer append(String str) | 追加内容 |
public synchronized StringBuffer delete(int start,int end) | 删除指定区间内的值(包含左边,不包含右边) |
public synchronized StringBuffer deleteChar(int index) | 删除指定位置的字符 |
public synchronized StringBuffer replace(int start,int end,String str) | 将指定区间的值替换为str |
public synchronized String substring(int start,int end) | 截取字符串 |
public synchronized StringBuffer insert(int offset,String str) | 在指定位置插入str |
public int indexOf(String str) | 从头开始查找指定字符的位置 |
public int indexOf(String str,int fromIndex) | 从fromIndex开始查找指定字符的位置 |
public synchronized StringBuffer reverse() | 进行反转 |
public synchronized toString() | 将StringBuffer转化为String |
注意:
1.为什么indexOf()
不用加synchronized关键字?因为indexOf()
是查找,允许多个线程同时读取,没有涉及写的操作,不存在安全隐患。
3.StringBuffer和StringBuilder的区别和联系
StringBuilder被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用到的时候。
StringBuilder和StringBuffer均是可变的字符串序列,而且方法也一样。但是因为StringBuffer的方法大多都由synchronized关键字修饰,是线程安全的,但是随之带来的问题就是效率比较低。
所以,多线程下操作字符串缓冲区下的大量数据用StringBuffer;单线程下操做字符串缓冲区下的大量数据用StringBuilder。