首页 > 编程笔记 > Java笔记 阅读:1

Java StringBuilder和StringBuffer的用法及区别(附带实例)

java.lang.StringBuffer 和 java.lang.StringBuilder 都是用于处理字符串的辅助类,二者提供的方法几乎一致。它们底层都是用一个长度为 16 的数组对象来存储字符串值,代码如下:
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
    public StringBuffer() {
        super(16);
    }

    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
    ......
}
无参数实例化一个 StringBuffer 或 StringBuilder 对象的过程,就是创建一个长度为 16 字符的字符串缓存区。

若实例化时传递了参数,则会根据当前传递参数对象的长度值来决定字符串缓存区大小,即“实际参数对象长度+16”。这预留的 16 个字符的空间用来对字符串进行修改,如字符串拼接等。

当你调用 append() 或其他字符串操作方法时,StringBuffer 先检查数组容量是否能够装下新字符串,若装不下,则会对数组进行扩容,代码如下:
abstract class AbstractStringBuilder {
    .....
    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;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
                ? hugeCapacity(minCapacity)
                : newCapacity;
    }
}
扩容的逻辑是创建一个新的 char 数组,将现有容量加一倍再加 2;若还是不够用,则其容量将等于所需容量大小。扩展完成后,将原始数组的内容复制到新数组中,最后将指针指向新的 char 数组。

StringBuffer和StringBuilder常用方法

StringBuffer 和 StringBuilder 类提供了很多操作字符串的方法,二者提供的方法几乎一样。对每种方法的详细描述,请参考 Java API 在线文档。

StringBuffer 与 StringBuilder 常用方法,如下表所示:

表:StringBuffer 与 StringBuilder 常用方法
方法 作用
StringBuffer append(CharSequence s) 拼接字符串
StringBuffer delete(int start, int end) 删除指定范围内的内容
StringBuffer replace(int start, int end, String str) 替换指定范围内的字符串
String substring(int start) 返回从指定位置截取的字符串
StringBuffer insert(int index, char[] str, int offset, int len) 插入字符串到指定位置

【实例】一个字符串为 hello,另一个字符串为 world,将两个字符串连接到一起,代码如下:
public class StringBufferBuilderDemo {
    public static void main(String[] args) {
        String str = "hello";
        String str1 = "world";
        StringBuffer sb = new StringBuffer(str);
        sb.append(str1);
        System.out.println(sb);
    }
}
程序运行结果为:

helloworld

上述代码显示,将 String 类型可以直接转换为 StringBuffer 类型,使用 StringBuffer 对象的 append() 方法进行拼接。

StringBuilder和StringBuffer的区别

StringBuilder 和 StringBuffer 两个类提供的字符串操作几乎完全相同。

值得注意的是,StringBuffer 几乎所有的方法都使用关键字 synchronized 声明,这意味着你创建的 StringBuffer 对象对多个线程可见,即这种方法能够保证同一时间点最多只有一个线程调用该方法,用以保证并发编程下的安全。这种处理方式,在保证字符串操作正常的情况下兼顾安全性,牺牲了性能。

而 StringBuilder 没有实现线程同步,虽然不能保证线程安全,但效率比 StringBuffer 高。

如果在实际开发过程中定义的字符串不涉及修改,那么建议使用 String;如果字符串需要更改,不考虑线程安全,希望系统有更好的效率,那么建议使用 StringBuilder;当需要考虑线程安全时,不管怎样,都应该使用 StringBuffer。

相关文章