18

我注意到该capacity方法返回StringBuilder容量......有时它的值等于字符串长度,有时它更大......

是否有一个方程式可以知道它的逻辑是什么?

4

8 回答 8

15

我将尝试用一些例子来解释这一点。

public class StringBuilderDemo {
     public static void main(String[] args) {
         StringBuilder sb = new StringBuilder();
         System.out.println(sb.length());
         System.out.println(sb.capacity());
     }
}

length()- 构建器中字符序列的长度,因为此字符串构建器不包含任何内容,所以它的长度将为 0。

capacity()- 已分配的字符空间数。当您尝试构造一个内容为空的字符串生成器时,默认情况下它会将初始化大小设为长度+16,即 0+16。所以容量会在这里返回 16。

注意:由 capacity() 方法返回的容量始终大于或等于长度(通常大于),并且会根据需要自动扩展以适应对字符串构建器的添加。

容量函数背后的逻辑:

  1. 如果您不使用任何内容初始化 stringbuilder,则默认容量将被视为 16 个字符的容量。
  2. 如果您使用任何内容初始化 stringbuilder,则容量将为内容长度+16。
  3. 当您向 stringbuilder 对象添加新内容时,如果当前容量不足以获取新值,则它将增长 (前一个数组容量+1)*2。

此分析取自实际的 StringBuilder.java 代码

于 2013-12-10T12:49:05.753 回答
15

当您附加到 时StringBuilder,会发生以下逻辑:

if (newCount > value.length) {
    expandCapacity(newCount);
}

其中newCount是所需的字符数,value.length是缓冲区的当前大小。

expandCapacity只是增加了背衬的大小char[]

ensureCapacity()方法是调用的公共方式expandCapacity(),其文档说:

确保容量至少等于指定的最小值。如果当前容量小于参数,则分配具有更大容量的新内部数组。新容量是以下两者中的较大者:

  • minimumCapacity 参数。
  • 旧容量的两倍,加上 2。

如果 minimumCapacity 参数为非正数,则此方法不执行任何操作并简单地返回。

于 2010-07-06T07:23:36.370 回答
5

此函数的作用与您的预期不同 - 它为您提供了此 StringBuilder 实例内存此时可以容纳的最大字符数。

字符串生成器必须阅读

于 2010-07-06T07:20:50.323 回答
2

逻辑如下:如果你定义了一个StringBuilder没有构造函数的类的新实例,就像这样new StringBuilder();,默认容量是 16。构造函数可以是 anint或 a String。对于String构造函数,默认容量是这样计算的

int newCapacity = string.length() + 16;

对于int构造函数,容量是这样计算的

int newCapacity = intSpecified + 16;

如果一个新String的附加到了StringBuilder并且新的长度String大于当前容量,那么容量计算如下:

int newCapacity = (oldCapacity + 1) * 2;
于 2018-03-16T13:03:48.867 回答
1

从 API:

每个字符串生成器都有容量。只要字符串构建器中包含的字符序列的长度不超过容量,就不需要分配新的内部缓冲区。如果内部缓冲区溢出,它会自动变大。

每当您追加某些内容时,都会检查以确保更新的 StringBuilder 不会超出其容量,如果超出,则调整 StringBuilder 的内部存储大小:

int len = str.length();
int newCount = count + len;
if (newCount > value.length)
  expandCapacity(newCount);

当向其中添加超过其容量的数据时,将根据以下公式重新调整大小:

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);
}

有关详细信息,请参阅src.zipJDK 附带的文件。(以上摘自 1.6 JDK 的片段)

于 2010-07-06T07:28:51.760 回答
1

编辑:道歉 - 以下是关于 .NET 的 StringBuilder 的信息,与原始问题并不严格相关。

http://johnnycoder.com/blog/2009/01/05/stringbuilder-required-capacity-algorithm/

StringBuilder 为您可能添加到其中的子字符串分配空间(很像 List 为其包装的数组创建空间)。如果您想要字符串的实际长度,请使用 StringBuilder.Length。

于 2010-07-06T07:21:47.363 回答
0

在 Java 1.8 中

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

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}

例如 :

StringBuilder str = new StringBuilder();  
System.out.println(str.capacity()); //16

str.append("123456789012345"); 
System.out.println(str.capacity()); //16

str.append("12345678901234567890"); 
System.out.println(str.capacity()); // 15 + 20 = 35
于 2019-11-02T07:43:16.263 回答
0

您可以进入 JDK 代码,看看它是如何工作的,它基于一个 char 数组:new char[capacity],它的工作方式类似于ArrayList何时使用 LinkedList 而不是 ArrayList?)。两者都使用数组来提高硬件效率,诀窍是分配一大块内存并在其中工作,直到内存不足并需要下一个大块继续(扩展/增长)。

于 2015-12-09T10:08:58.610 回答