hello,大家好啊,不知道大家在平时的工作、学习中List用的多不多,这个我猜比Thread用的人多多了,人均会用
今天就和大家一起看一下一些List的源码
用的最最最最最多的List之ArrayList:
先看看ArrayList里面有哪些属性
/** 默认容量,当不传入初始化容量时默认为10,但是不是在构造时初始化的,是在第一次添加时扩容的 */
private static final int DEFAULT_CAPACITY = 10;
/** 空实例的空实现(用于构造函数传入初始化容量为0或传入的集合长度为0) */
private static final Object[] EMPTY_ELEMENTDATA = {
};
/** 如果不传入初始化容量默认elementData为这个 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
};
/** 用上面这两个空数组确定是有参构造还是无参构造 */
/** 数组 */
transient Object[] elementData; // non-private to simplify nested class access
/** 省略 */
private int size;
接下来看其添加操作:
整个add()方法非常简单,ensureCapacityInternal()确定内部容量(是否需要扩容),在数组的下一个位置放入该元素即可
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
这个直接跳过,我们看其内部的两个具体方法
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
计算容量:也就是看当前数组是否初始化了,没初始化就返回DEFAULT_CAPACITY
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 这里的minCapacity = 当前size + 1
// 如果是无参构造创建的,即当前内部数组并没有初始化
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 返回DEFAULT_CAPACITY
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
确定是否要扩容:
判断添加元素(size + 1)过后 是否大于 当前 数组长度 ,大于则扩容
如果上一步是未初始化返回DEFAULT_CAPACITY,这里的当前数组长度就为0,也是需要扩容的
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
这是真正的扩容方法,前面都只是前戏😀
首先按照当前容量扩大1.5倍,看看够不够,不够就取当前需要的容量
当然不能太大,最多就Integer.MAX_VALUE,不能再多了
复制一个新的数组,容量为新容量
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// 把当前容量扩大1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 扩大1.5倍都还不够
if (newCapacity - minCapacity < 0)
// 就取minCapacity
newCapacity = minCapacity;
// 大于上限了
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 要不的要不得,最高就Integer.MAX_VALUE,不能再高了
newCapacity = hugeCap