admin管理员组文章数量:1612099
StringBuffer大家一定不陌生吧,今天浅谈一下StringBuffer中capacity的扩增机制。
因为StringBuffer实际通过一个char[]引用来保存字符串的,它的长度是固定的。
如果append的值超过了数组容量,将会执行一个扩容方法,生成一个新数组,并将旧数组的值copy进去并替代。
一、capacity( ) 与length ( )
先来个小栗子:
StringBuffer sb = new StringBuffer();
System.out.println(" this initial capacity: " + sb.capacity());
System.out.println(" this length: " + sb.length());
结果是这样的,我们来看StringBuffer的源码就不难理解了。
this initial capacity: 16
this length: 0
StringBuffer构造函数:
/**
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuffer() {
super(16);
}
StringBUffer实现的AbstractStringBuilder接口的构造函数:
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
二、StringBuffer的append
StringBuffer sb1 = new StringBuffer(" Hello World!!! ");
System.out.println(" this capacity: " + sb1.capacity());
System.out.println(" this length: " + sb1.length());
StringBuffer sb2 = new StringBuffer();
sb2.append(" Hello World!!! ");
System.out.println(" this capacity: " + sb2.capacity());
System.out.println(" this length: " + sb2.length());
这里打印出来应该是多少呢?结果让人出乎意料。
this capacity: 32
this length: 16
this capacity: 16
this length: 16
这是为什么呢?我们来看看带参构造函数:
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
原来他会把传入的字符串再加16。。。
三、capacity的扩容机制
我简单的写了一个循环来往StringBuffer里面append字符串,并监测容量的变化。
StringBuffer sb1 = new StringBuffer();
for (int num = 0; num < 5; num++) {
sb1.append("12345678");
System.out.println(" this capacity: " + sb1.capacity());
System.out.println(" this length: " + sb1.length());
System.out.println("---------------------------------");
}
直接上结果:
this capacity: 16
this length: 8
---------------------------------
this capacity: 16
this length: 16
---------------------------------
this capacity: 34
this length: 24
---------------------------------
this capacity: 34
this length: 32
---------------------------------
this capacity: 70
this length: 40
---------------------------------
每次循环append了一个长度是8的字符串,他的容量变化:
16 - 16 - 34 - 34 - 70
结论:capacity增长的规律为 旧值*2+2
增长顺序怎么是这样的呢?
我们来深入源码:
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
return append("null");
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
//如果minimumCapacity大于原容量*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);
}
四、可大不可小的capacity
我们再来个例子,看看capacity的变化情况
StringBuffer sb1 = new StringBuffer();
System.out.println(" before ensure: " + sb1.capacity());
sb1.ensureCapacity(10);
System.out.println(" now capacity " + sb1.capacity() + " first ensureCapacity: " + sb1.capacity());
sb1.ensureCapacity(20);
System.out.println(" now capacity " + sb1.capacity() + " second ensureCapacity: " + sb1.capacity());
sb1.ensureCapacity(80);
System.out.println(" now capacity " + sb1.capacity() + " third ensureCapacity: " + sb1.capacity());
before ensure: 16
now capacity 16 first ensureCapacity: 16
now capacity 34 second ensureCapacity: 34
now capacity 80 third ensureCapacity: 80
当设置StringBuffer的容量
1、小于当前容量时,容量不变。
本例中,容量依然为16。
2、大于当前容量,并且小于(当前容量+1)*2,则容量变为(当前容量+1)*2。
本例中,16<20<(16+1)*2=34,所以容量为34。
3、大于当前容量,并且大于(当前容量+1)*2,则容量变为用户所设置的容量。
本例中,80>16,80>(16+1)*2=34,所以容量为80。
原因再源码中可以找到:
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
//参数小于原容量时,容量不变
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);
}
本文标签: 机制StringBufferCapacity
版权声明:本文标题:StringBuffer中的capacity的扩增机制 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1728620287a1166268.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论