Java StringBuffer附加分配

时间:2010-10-21 01:49:02

标签: java stringbuffer

在java中使用StringBuffer时,我想知道在需要重新分配空间时如何实现append函数。

例如,如果我追加一个比当前分配的空格更长的字符串,它如何在方法的细节中管理它?

2 个答案:

答案 0 :(得分:5)

源代码包含在JDK下载中。只需查找src.zip文件(我的是Program Files(x86)\ Java \ jdk1.6.0_01 \ src.zip)。解压后,只需转到java / lang,就可以检查StringBuffer.java,StringBuilder.java和AbstractStringBuilder.java。

在此实现中,AbstractStringBuilder中的“expandCapacity”看起来像计算容量并执行Arrays.copyOf()来扩展缓冲区。值得注意的是,第一次检查是针对< 0以防止溢出情况。

void expandCapacity(int minimumCapacity) {
    int newCapacity = (value.length + 1) * 2;
    if (newCapacity < 0) {
        newCapacity = Integer.MAX_VALUE;
    } else if (minimumCapacity > newCapacity) {
        newCapacity = minimumCapacity;
    }
    value = Arrays.copyOf(value, newCapacity);
}

答案 1 :(得分:4)

Apache Harmony实施依赖于AbstractStringBuilder中的方法来管理添加/删除(StringBuffer extends AbstractStringBuilder)。

AbstractStringBuilder保留一个字符缓冲区(即char s的数组)来保存当前的“字符串”。将任何对象的下一个字符串表示附加到此缓冲区时,它会检查缓冲区是否包含足够的空间,如果空间不足,则会分配新的字符缓冲区,复制旧缓冲区,然后将新字符串添加到该缓冲区。我们可以从enlargeBuffer

的内部收集这些内容
private void enlargeBuffer(int min) {
    int newSize = ((value.length >> 1) + value.length) + 2;
    char[] newData = new char[min > newSize ? min : newSize];
    System.arraycopy(value, 0, newData, 0, count);
    value = newData;
    shared = false;
 }

...当超出value(保存char缓冲区的私有成员)的容量时,在任何append方法中调用此方法:

final void append0(char chars[]) {
    int newSize = count + chars.length;
    if (newSize > value.length) {
         enlargeBuffer(newSize);
     }
     System.arraycopy(chars, 0, value, count, chars.length);
     count = newSize;
}

标准的OpenJDK实现非常相似。同样,StringBuffer依赖于AbstractStringBuilder

void expandCapacity(int minimumCapacity) {
    int newCapacity = (value.length + 1) * 2;
    if (newCapacity < 0) {
        newCapacity = Integer.MAX_VALUE;
    } else if (minimumCapacity > newCapacity) {
        newCapacity = minimumCapacity;
    }
    value = Arrays.copyOf(value, newCapacity);
}

请注意Arrays.copyOf复制字符数组value用空字符填充它,使其总大小为newCapacity,这基本上等同于和声方法中的new char[...]调用。同样,当没有足够的空间来添加下一个字符串段时,会调用expandCapacity方法:

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