public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}
说明:java
//数组默认大小10 private static final int DEFAULT_CAPACITY = 10; //默认数据 空数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
这里用transient
修饰,是为了防止自动序列化。缘由:数组
因为 ArrayList 是基于动态数组实现的,因此并非全部的空间都被使用。所以使用了 transient 修饰,能够防止被自动序列化。
因此,ArrayList也自定义了序列化和反序列化方法,只序列化当前存放的数据安全
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ int expectedModCount = modCount; s.defaultWriteObject(); s.writeInt(size); // 这里只序列化已经有的数据,并非全部空间都序列化 for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; s.defaultReadObject(); s.readInt(); if (size > 0) { int capacity = calculateCapacity(elementData, size); SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity); ensureCapacityInternal(size); Object[] a = elementData; // 反序列化,读取数据 for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
private int size;//ArrayList的数组大小
//修改次数 父类AbstractList全部 protected transient int modCount = 0; //指望修改次数 父类AbstractList的内部类Itr全部 int expectedModCount = modCount;
说明多线程
ArrayList的全部关于结构变化的操做(add、remove、addAll、removeRange和clear),都会让modCount++ 而在私有内部类迭代器Itr中定义了变量expectedModCount和checkForComodification方法 private class Itr implements Iterator<E> { //指望的修改次数 int expectedModCount = modCount; //修改检查方法() final void checkForComodification() { //若是修改数和指望修改数不一致,抛出异常 if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
好处:快速失败dom
若是在多线程环境中,使用迭代器操做ArrayList的时候可能形成修改次数不一致,每次迭代器更新数据前检查,来保证数据安全和一致,若是不一致能让迭代快速失败
public boolean add(E e) { ensureCapacityInternal(size + 1); // 扩容(若是必要),而且 modCount++ elementData[size++] = e;//数组尾部添加元素 return true; }
//在指定位置添加元素 public void add(int index, E element) { rangeCheckForAdd(index);//校验index是否大于数组长度或者小于0 ensureCapacityInternal(size + 1); // 扩容(若是必要),而且 modCount++ //对数据进行复制,目的是把 index 位置空出来放本次插入的数据,并将后面的数据向后移动一个位置 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element;//将插入的值放到指定位置index size++;//将 size + 1 }
public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); //数组复制和移动 System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
在指定位置设置新的值,并返回旧值this
public E set(int index, E element) { rangeCheck(index);//检查index是否超过数组大小 E oldValue = elementData(index);//获取到以前的值 elementData[index] = element;//设置新值 return oldValue;//返回以前的值 }
//扩容检测 private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // private void ensureExplicitCapacity(int minCapacity) { modCount++; // 当数组容量不足,调用grow进行扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //扩容 private void grow(int minCapacity) { int oldCapacity = elementData.length;//获取当前容量大小 int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量=当前容量的1.5倍 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); }
public E get(int index) { rangeCheck(index);//检查index是否超过数组大小 return elementData(index);//返回数组指定位置的元素 }
移除指定位置元素,返回被移除位置上的元素值线程
public E remove(int index) { rangeCheck(index);//index合法检查 modCount++;//修改次数++ E oldValue = elementData(index);//获取旧值 int numMoved = size - index - 1;//计算该位置后面的数组大小 if (numMoved > 0) //从新移动数组 System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; //清除数组,让gc收集 return oldValue; }
public boolean remove(Object o) { if (o == null) {//移除null值 for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else {//移除非null值 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //快速移除,数组复制和移动 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }
线程安全code
Vector相似于ArrayList,是一个动态数组,只是它是一个线程安全的数组容器。它的add、set、remove方法都是用synchronized来修饰的。
扩容对象
//Vector的扩容,不是按1.5倍,二是1倍 private void grow(int minCapacity) { int oldCapacity = elementData.length; //按原来的1倍扩容 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }