基于jdk8
1.首先我们看new ArrayList中
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
ArrayList底层就是一个Object数组;
这里DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个静态的空的Object数组,所以ArrayList初始容量实际是0;
2.add方法
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private int size;
这里size默认值为0
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private static final int DEFAULT_CAPACITY = 10;
默认DEFAULT_CAPACITY容量为10,但是这是在使用add方法时,ArrayList才会进行初始化容量赋值。
首次加载时,elementData 对象肯定是一个空的Object数组,所以minCapacity = 10;
3.接下来我们再看看ensureExplicitCapacity这个方法;
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
首次加载时minCapacity = 10,所以minCapacity - elementData.length肯定大于0,然后进行扩容判断
还有就是当数组大小超过原有容量之后会进行扩容。扩容大小为 old +(old/2) -->1.5倍
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 final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
初次加载,oldCapacity = 0,所以newCapacity=0;newCapacity - minCapacity <0,所以最后初始化加载时newCapacity 为10了。
最后 newCapacity 会与MAX_ARRAY_SIZE进行比较,不能超过Integer的最大值减8
The maximum size of array to allocate.
Some VMs reserve some header words in an array.
Attempts to allocate larger arrays may result in
OutOfMemoryError: Requested array size exceeds VM limit
vm虚拟机会在数组中存放一些数据,所以不能等于Integer.MAX_VALUE(2147483647)
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
--拓展--
因为ArrayList底层是一个Object数组,在多线程环境中可以会出现并发争抢的问题,
java提供三种解决方案:
1.new Vector jdk1.0就出现的类
public void add(E e) { int i = cursor; synchronized (Vector.this) { checkForComodification(); Vector.this.add(i, e); expectedModCount = modCount; } cursor = i + 1; lastRet = -1; }
加了synchronized保证add方法线程安全性,但是并发性急剧下降,所以在jdk1.2中才
会出现ArrayList这个类。
2.Collections.SynchronizedList(new ArrayList());
public boolean add(E e) { synchronized (mutex) {return c.add(e);} }
3.new CopyOnWriteArrayList();
private transient volatile Object[] array;
使用volatile关键字,保证array数组可见性,禁止指令重排;
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
add方法添加ReentrantLock 可重入锁(递归锁),保证add方法在多线程环境中程序执行
的安全性。