我注意到capacity
方法在没有逻辑的情况下返回StringBuilder
容量
方式......有时它的值等于字符串长度,而其它时间更长......
是否知道哪个是其逻辑?
答案 0 :(得分:13)
当您追加到StringBuilder
时,会发生以下逻辑:
if (newCount > value.length) {
expandCapacity(newCount);
}
其中newCount
是所需字符数,value.length
是缓冲区的当前大小。
expandCapacity
只会增加支持char[]
ensureCapacity()
方法是调用expandCapacity()
的公开方式,其文档说:
确保容量至少等于指定的最小值。如果当前容量小于参数,则分配具有更大容量的新内部阵列。新容量是更大的:
- minimumCapacity参数。
- 旧容量的两倍,再加上2.
如果minimumCapacity参数为非正数,则此方法不执行任何操作,只返回。
答案 1 :(得分:11)
我将尝试用一些例子解释这一点。
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb.length());
System.out.println(sb.capacity());
}
}
length()
- 构建器中字符序列的长度
由于此stringbuilder不包含任何内容,因此其长度为0.
capacity()
- 已分配的字符空间数。
当您尝试构造具有空内容的stringbuilder时,默认情况下,它将初始化大小设为length + 16,即0 + 16。因此容量将在这里返回16。
注意:capacity()方法返回的容量始终大于或等于长度(通常大于),并将根据需要自动扩展以适应字符串构建器的添加。
容量功能背后的逻辑:
答案 2 :(得分:4)
此函数执行与您预期不同的操作 - 它为您提供此StringBuilder实例内存此时可以容纳的最大字符数。
答案 3 :(得分:1)
编辑:道歉 - 以下是有关.NET的StringBuilder的信息,与原始问题并不严格相关。
http://johnnycoder.com/blog/2009/01/05/stringbuilder-required-capacity-algorithm/
StringBuilder为您可能添加到它的子字符串分配空间(很像List为它包装的数组创建空间)。如果您想要字符串的实际长度,请使用StringBuilder.Length。
答案 4 :(得分: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);
}
有关详细信息,请参阅JDK随附的src.zip
文件。 (以上摘自1.6 JDK的片段)
答案 5 :(得分:1)
这是逻辑:
如果您在没有构造函数的情况下定义StringBuilder
类的新实例,那么new StringBuilder();
的默认容量为16。
构造函数可以是int
或String
。
对于String
构造函数,默认容量计算如下
int newCapacity = string.length() + 16;
对于int
构造函数,容量计算方式如下
int newCapacity = intSpecified + 16;
如果新String
附加到StringBuilder
并且String
的新长度大于当前容量,则容量计算如下:
int newCapacity = (oldCapacity + 1) * 2;
答案 6 :(得分:0)
你可以进入JDK代码并看看它是如何工作的,它基于一个char数组:new char[capacity]
,它类似于ArrayList
的工作方式(When to use LinkedList over ArrayList?)。两者都使用数组“硬件高效”,诀窍是分配大量内存并在其中工作,直到你的内存不足并需要下一个大块继续(扩展/增长)。
答案 7 :(得分: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