StringBuilder 和 常用容器初始化容量时尽量定初始化容量,有助于提高性能。
分析:
StringBuilder StringBuffer 与ArrayList对象一样都是可变容量的。
底层实现都是char[] ,以数组形式实现的。
/** * The value is used for character storage. */
char[] value;
|
大家都知道数组是定长的(确定了长都就不可改变的),那么他是如何实现变长的呢,看下面源码
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;
}
|
/** * This method has the same contract as ensureCapacity, but is * never synchronized. */ 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) {
//每次扩容使原有的2倍加2
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);
}
|
看完上面的源码,我们知道容量不够用了就重新创建数组(也就是重新分配内存空间),这些操作都是耗时间和资源的的,如果我们在初始化时定了一个接近的容量,速度会有一定的提升
StringBuffer,ArrayList 等和这个扩容方法也是大同小异,所以我们一定要重视初始化容量的问题。