ArrayList 重点
- 1.ArrayList中维护了一个Object类型的数组elementData
- 2.当创建ArrayList对象时,如果使用无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10;如需要再次扩容,则扩容elementData当前容量的1.5倍。
- 3.如果使用指定大小的构造器,则初始elementData容量为指定的大小,如果需要扩容,则扩容elementData当前容量的1.5倍。
- 4.扩容时使用Arrays.copyOf(elementData,newCapacity)的方式,保留原有数据的同时增加一些空间。
private void grow(int minCapacity) {
// overflow-conscious code
//获取当前容量
int oldCapacity = elementData.length;
//获取新的容量(将当前容量的二进制数右移1位后再转为十进制,其实就是当前容量的1.5倍)
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新容量比指定的容量小
if (newCapacity - minCapacity < 0)
//将指定容量作为新容量
newCapacity = minCapacity;
//如果新容量比最大数组容量(MAX_ARRAY_SIZE,即2的31次方-9)还要大
if (newCapacity - MAX_ARRAY_SIZE > 0)
//需要通过hugeCapacity方法进一步确定新容量了,否则新容量依然是当前容量的1.5倍。
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//创建一个类型相同,长度为newLength的数组,并将其返回
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private static int hugeCapacity(int minCapacity) {
//指定容量小于0,就抛一个内存溢出异常;
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//如果指定容量大于最大数组容量(MAX_ARRAY_SIZE,即2的31次方-9),就返回最大的整数2的31次方减一,否则就返回最大数组容量
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
拓展问题
- 为什么最大数组容量要比最大整数相差为8呢?
原因:一些vm在数组中保留了标题。尝试分配较大的数组可能会导致*OutOfMemory错误
- ArrayList 是线程不安全的,如何再多线程中使用呢?
使用以下方式:
1.List list= Collections.synchronizedList(new ArrayList<>());
2.Vector
- Collections.synchronizedList和Vector 实现同步的区别?
区别在于:
SynchronizedList使用同步代码块实现同步,锁定的对象为mutex(构造 函数可以传入一个Object,如果在调用的时候显示的传入一个对象,那么锁定的就是用户传入的对象,反之锁定this对象);
Vector使用同步方法实现同步,锁定this对象;
- 当我们删除元素时,ArrayList 的容量会减少吗?
ArrayList的容量不会减少但是可以使用trimToSize()方法,将ArrayList的容量调整到当前列表的大小,
应用程序可以使用此操作来最小化ArrayList实例的存储。