* ArrayList源码分析
* jdk7和jdk8版本有一些不同
首先,不管7版本还是8版本,ArrayList底层存储没有改变
private transient Object[] elementData;
在使用的时候,最简单的使用方式为:
ArrayList list = new ArrayList();
1.所以首先看ArrayList源码中的空参构造器
public ArrayList() {
this(10);
}public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
从源码可以看出,空参的时候,初始化的长度就是为10。
即new ArrayList();会创建一个长度为10的Object类型 数组
2.在ArrayList中的add方法:
第一次添加的时候,size大小为0
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
3.在添加数据时候,先回去list的容量是否够用,如果开辟的空间不够用,会执行grow方法进行扩容
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
4.数组元素扩容方式
扩容后的长度:
oldCapacity:首先记录底层数组扩容前的长度
newCapacity:新的容量大小就是为旧的容量 + 旧的容量 右移一位
即 新的容量 = 旧的容量 + 旧的容量 / 2 = 1.5 * 旧的容量 (结果使用向下取整)
如果新的容量比需要扩容的容量还要小,直接使用需要扩容的容量作为长度
如果新的容量大于数组最大容量,直接使用Integer.MAX_VALUE作为最大长度
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: 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; }
扩容后的长度总结:
扩容时,首先会将扩容容量设置为原容量的1.5倍(向下取整)
如果扩容容量还是小于需要的容量,直接使用新的容量长度作为扩容容量
如果新的容量大于数组容量最大值,直接采用Integer.MAX_VALUE作为扩容容量。
容量确定后会讲数据以新的长度拷贝到新的数组中
通过以上
建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity);
public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; }
在JDK8中
在实例化的时候,底层会初始化一个 {} 的数组,即创建空的Object
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
在第一调用add方法的时候,底层才会开始创建长度为10的数组,后续的添加和扩容操作与jdk7一致。
总结
jdk7中的ArrayList使用时候就会创造出长度为10的数组
jdk8中只有在使用开始放入数据才会开始创建数组,会延迟数组的创建时间,节省内存
来源:CSDN
作者:weixin_44641024
链接:https://blog.csdn.net/weixin_44641024/article/details/103839251