Java 的 StringBuilder 是怎么实现的?

2024-08-26 08:11:08 318
`StringBuilder` 是 Java 中一个用于处理可变字符串的类,它在单线程环境下具有较高的性能。`StringBuilder` 的实现主要依赖于一个可变的字符数组(`char[]`),通过操作这个数组来管理字符串的内容。下面是 `StringBuilder` 的主要实现细节:

1. 底层数据结构

StringBuilder 的底层是一个可变长度的字符数组 value。这个数组用于存储字符串的字符数据。

核心字段

class StringBuilder {
    // 用于存储字符数据的数组
    char[] value;
    // 记录当前字符串的长度
    int count;
    
    // 初始容量为16
    static final int DEFAULT_CAPACITY = 16;
}

2. 构造方法

StringBuilder 提供了多个构造方法,可以根据需要初始化字符数组的容量。

常用构造方法

public StringBuilder() {
    this(DEFAULT_CAPACITY);  // 默认容量为16
}

public StringBuilder(int capacity) {
    value = new char[capacity];
}

public StringBuilder(String str) {
    value = new char[str.length() + DEFAULT_CAPACITY];
    append(str);
}

3. append 方法

append 方法是 StringBuilder 中最常用的方法之一,它用于在当前字符串的末尾追加字符或字符串。append 方法的实现包括两个主要步骤:检查是否需要扩容,并将新内容复制到 value 数组中。

append 方法的实现

public StringBuilder append(String str) {
    if (str == null) str = "null";
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

步骤解析

  1. 检查容量ensureCapacityInternal 方法用于检查当前字符数组的容量是否足够容纳新的字符,如果不够则进行扩容。
  2. 复制内容getChars 方法将 str 中的字符复制到 value 数组的末尾位置。
  3. 更新计数器count 记录了当前字符串的长度,在追加新内容后更新它。

4. 扩容机制

StringBuilder 的扩容机制在 append 时起关键作用。如果当前字符数组的容量不足以容纳新追加的内容,StringBuilder 会自动扩容,通常会将容量扩大到原来的 2 倍左右。

扩容实现

private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0)
        expandCapacity(minimumCapacity);
}

void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) { // 溢出处理
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

步骤解析

  1. 判断是否需要扩容ensureCapacityInternal 方法判断当前数组容量是否足够。
  2. 计算新容量expandCapacity 方法计算扩容后的新容量,通常为当前容量的两倍加二,以应对数组增长需求。
  3. 数组扩容:通过 Arrays.copyOf 方法将原数组内容复制到新扩展的数组中。

5. toString 方法

StringBuilder 最终会通过 toString 方法将内容转换为不可变的 String 对象。

toString 方法的实现

public String toString() {
    return new String(value, 0, count);
}

步骤解析

  • 创建一个新的 String 对象,将 StringBuilder 当前字符数组中的内容复制到新的 String 中。

总结

StringBuilder 通过一个可变的字符数组实现字符串的动态操作,append 等方法会根据需要自动扩容,并将新内容追加到数组中。StringBuilder 的设计保证了在频繁操作字符串的场景下具备较高的性能,尤其是在单线程环境中,不需要为线程安全付出额外的开销。