了解Java咖啡的最好的方式就是从源码入手,因为源码是最真实的第一手资料,如果仅仅是阅读别人的公众号文章和博客解读,因为人非圣贤,总会出现理解偏差,故是相对较次的手段。本文帮助一些阅读上有困难的朋友对源码的基础上加以自身理解的注释,希望大家能喜欢。
ArrayList.add( )源码
public boolean add(E e) {
// 确保有充足的空间可以容纳 新元素
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
ArrayList.ensureCapacityInternal( )源码
// minCapacity 指的是至少需要的槽位长度
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
//The number of times this list has been <i>structurally modified</i>.
//容器长度改变的次数
modCount++;
// overflow-conscious code
// 如果需要的最小容器槽位数量大于当前元素长度,意味着根本容不下新元素
//所以赶紧扩容吧!!!
if (minCapacity - elementData.length > 0)
// 开始扩容!
grow(minCapacity);
}
ArrayList.grow( ),这个函数才是真正的扩容过程,其中的要点是
1、盲目可以扩容1.5倍
2、确定1.5倍扩容是否合理
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新的容量=旧的容量*1.5呗;至于位运算嘛,就是为了快。
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 扩容后的容量值还变的更小了?咋回事?
// 我猜猜:minCapacity*1.5>Integer.MAX_VALUE会出现这种局面
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
//扩容后超过了允许的最大容量,说明1.5倍后扩容的已经不合理了。
if (newCapacity - MAX_ARRAY_SIZE > 0)
//重新确定扩容后的容量,如何确定呢?
//1.需要最小容量minCapaCity<0,意味继而上一次扩容后,已经溢出int范围
//2.在minCapacity在 MAX_ARRAY_SIZE 与 Integer.MAX_VALUE 之间,则直接扩容
// newCapacity=Integet.MAX_VALUE。
//3.minCapacity <= MAX_ARRAY_SIZE则可以扩容到,
// 在前面一系列的操作下,不会出现minCapacity很小,newCapacity大到不合理的情况.
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:,
// 扩容后用Arrays.copy,将数据转移到新的容器数组,并赋值给原引用。
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
理解有所偏差的话,望指正!