admin管理员组文章数量:1612066
StringBuilder的容量capacity变化,是每次2倍增长吗?(jdk1.8)
测试代码 1
StringBuilder sb = new StringBuilder();
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("000");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
运行结果 1
16----0
16----16
34----19
70----35
70----51
测试代码 2
StringBuilder sb = new StringBuilder();
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0000");
System.out.println(sb.capacity() + "----" + sb.length());
运行结果 2
16----16
35----35
问题
从运行结果1和运行结果2都能看出,StringBuilder的容量变化规律貌似不再是网上很多人所说的那样(容量默认为16,追加数据时,如果容量不够,则每次2倍整地扩容,直到容量不小于StringBuilder的长度值为止。)
那容量的变化规律到底是什么样的呢?接下来进入源码进行分析。
测试代码 1 的源码分析
public StringBuilder() {
super(16);
}
// StringBuilder的父类AbstractStringBuilder
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* 该变量用于存储字符(可见StringBuilder底层用的是字符数组实现的)
* The value is used for character storage.
*/
char[] value;
/**
* 已使用的字符个数
* The count is the number of characters used.
*/
int count;
// ...
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
// ...
}
先进入StringBuilder的构造方法,其又调用了父类的构造,初始化容量capacity依然还是16。这就是为何运行结果1中第一组数据中容量capacity为16的原因。
sb.append("0000_0000_0000_0");执行后因为长度还是16,没有超过当前容量(capacity = 16)的范围,所以运行结果还是不变。
sb.append("000");执行后,容量capacity突然变为34,竟然不是2*16=32,why?容量因为这句代码的执行发生了改变,那么容量的变化规则一定在append方法之中。进入append方法的源码发现:
ensureCapacityInternal(count + len);这句代码就是重点,用于计算容量的大小的。
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
//调用该方法,确定最终容量Capacity
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)
expandCapacity(minimumCapacity);
}
其中minimumCapacity即为(count + len)的值,即 (已使用的字符个数 + 追加的新串的长度)的和(16 + 3 = 19),暂且叫最小容量值。
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);
}
起初value.length为容量的默认值16,因newCapacity = value.length * 2 + 2;所以有newCapacity = 34即追加后的新容量为34。
容量的变化规律是2倍+2?
从测试代码1看起来下面的测试代码也能证明貌似是这样的,但是测试代码2的运行结果如何解释呢?,看源码,下面还有一句:
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
这句代码的意思是,如果原容量的2倍再加2的结果还小于最小容量值minimumCapacity的话,新的容量将按照最小容量值minimumCapacity来计算。此刻一切都明白了。
总结
StringBuilder的容量Capacity变化规则为:
初始值为16;
如果minimumCapacity(新添加的数据长度和已有数据长度的和)小于当前容量Capacity,则添加数据后容量Capacity不变;
如果minimumCapacity(新添加的数据长度和已有数据长度的和)大于当前容量Capacity,但minimumCapacity**小于**当前容量Capacity的2倍加2,则添加数据后容量Capacity变为上次容量的2倍加2;
如果minimumCapacity(新添加的数据长度和已有数据长度的和)大于当前容量Capacity的2倍加2,则添加数据后容量Capacity即为minimumCapacity(新添加的数据长度和已有数据长度的和)。
初始值 原容量 < 总内容 <= 2 * 原容量 + 2 总内容 > 2 * 原容量 + 2
16 2 * 原容量 + 2 内容总长度
---------------------
作者:cuncaojin
来源:CSDN
原文:https://blog.csdn/cuncaojin/article/details/78925234
版权声明:本文为博主原创文章,转载请附上博文链接!
本文标签: 容量规则StringBuilderCapacity
版权声明:本文标题:StringBuilder的容量capacity变化规则 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1728620096a1166242.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论