前言 今天阅读ArrayList和Vector的源码,了解其底层结构和扩容机制
首先,需要知道的是
ArrayList和Vector底层都是可变数组实现
ArrayList非线程安全,Vector是线程安全的
对比一下ArrayList和Vector的常量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class ArrayList <E> extends AbstractList <E> implements List <E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L ; private static final int DEFAULT_CAPACITY = 10 ; private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; transient Object[] elementData; private int size; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Vector <E> extends AbstractList <E> implements List <E>, RandomAccess, Cloneable, java.io.Serializable { protected Object[] elementData; protected int elementCount; protected int capacityIncrement; private static final long serialVersionUID = -2767605614048989439L ; }
总结一下,ArrayList和Vector的底层都是通过缓存数组来实现的
ArrayList的elementData使用transient关键字修饰,不参与对象的序列化
而Vector的elelmentData没有参与对象的序列化,至于原因,网上说是因为重写了writeObject方法,因为Vector本质就是线程安全的,我不是很理解,希望有大佬再解释一下
对比构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public ArrayList () { this .elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList (int initialCapacity) { if (initialCapacity > 0 ) { this .elementData = new Object [initialCapacity]; } else if (initialCapacity == 0 ) { this .elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException ("Illegal Capacity: " + initialCapacity); } } public ArrayList (Collection<? extends E> c) { Object[] a = c.toArray(); if ((size = a.length) != 0 ) { if (c.getClass() == ArrayList.class) { elementData = a; } else { elementData = Arrays.copyOf(a, size, Object[].class); } } else { elementData = EMPTY_ELEMENTDATA; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public Vector () { this (10 ); } public Vector (int initialCapacity) { this (initialCapacity, 0 ); } public Vector (int initialCapacity, int capacityIncrement) { super (); if (initialCapacity < 0 ) throw new IllegalArgumentException ("Illegal Capacity: " + initialCapacity); this .elementData = new Object [initialCapacity]; this .capacityIncrement = capacityIncrement; } public Vector (Collection<? extends E> c) { Object[] a = c.toArray(); elementCount = a.length; if (c.getClass() == ArrayList.class) { elementData = a; } else { elementData = Arrays.copyOf(a, elementCount, Object[].class); } }
对比而言,Vector的构造具有更多的自主性,开发者可以限定扩容时的增长值
扩容机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public boolean add (E e) { ensureCapacityInternal(size + 1 ); elementData[size++] = e; return true ; } private void ensureCapacityInternal (int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity (Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity (int minCapacity) { modCount++; if (minCapacity - elementData.length > 0 ) grow(minCapacity); }
当ArrayList添加元素时,会先将当前实际元素容量和缓存数组容量做对比,大小不够时则考虑扩容
1 2 3 4 5 6 7 8 9 10 11 12 public synchronized boolean add (E e) { modCount++; ensureCapacityHelper(elementCount + 1 ); elementData[elementCount++] = e; return true ; } private void ensureCapacityHelper (int minCapacity) { if (minCapacity - elementData.length > 0 ) grow(minCapacity); }
当Vector添加元素时,同ArrayList,容量不够则考虑扩容
其中,ArrayList多出的代码主要是因为Vector在无参构造时,默认初始化了10个空间,而ArrayList在添加第一个元素时,若缓存数组容量为默认值(空数组),则也给一个初始化的大小(10)
另外,Vector的add函数加上了同步锁,保证了线程的安全性
ArrayList扩容细节 1 2 3 4 5 6 7 8 9 10 11 private void grow (int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1 ); if (newCapacity - minCapacity < 0 ) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0 ) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
一目了然,newCapcity = oldCapcity + ( oldCapcity >> 1 )
进行1.5倍扩容 若初始化空间为10 那么容量大小变化就为 10 -> 15 -> 22 -> 33 -> ……
Vector扩容细节 1 2 3 4 5 6 7 8 9 10 11 private void grow (int minCapacity) { int oldCapacity = elementData.length; 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); }
Vector中,若开发者没有自定义增长容量,则按2倍扩容,否则每次在当前容量的基础上加上开发者自定义的增长容量