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。

原文地址:https://www.cnblogs.com/wind-and-sky/p/15505608.html