java ArrayList源码分析
2018-03-12 22:08
573 查看
继承了AbstractList抽象类(该类继承了AbstractCollection和List接口)实现了List, RandomAccess, Cloneable, java.io.Serializable接口。
序列化ID:
默认容量为10:
底层是数组:
三个构造函数:分别是带容量的参数,无参,和带Collection参数的构造函数。
给ArrayList瘦身,且和size一样大(size是已经使用的容量)。用Arrays.copyOf复制了已经使用的那部分组成一个新的数组相当于把尾巴多出的容量给剪掉了。
扩容:可以看到默认扩充newCapacity是oldCapacity的1.5倍,如果传入了参数miniCapacity就会当成新的扩充容量,这里还考虑了整型上限问题,最多只能扩充到0x7fffffff。
在执行add()方法时,我们看到会调用这样一条方法
同样addAll()也类似,扩容的容量取决于加入集合的长度:
在执行add()或者remove()方法时,我们能看到底层调用的还是
在这里通过调用clear()我们可以看到底层只是通过将元素置空,等待GC自动回收。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
序列化ID:
private static final long serialVersionUID = 8683452581122892189L;
默认容量为10:
private static final int DEFAULT_CAPACITY = 10;
底层是数组:
//空的对象数组 private static final Object[] EMPTY_ELEMENTDATA = {}; //空的对象数组和上面的区别在于当添加第一个元素时知道扩充多少容量 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //相当于是个缓冲区,任何空的ArrayList满足elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA时会被扩充成默认容量(10)在第一个元素被添加的时候。 transient Object[] elementData;//transient 代表该类在序列化时阻止该变量持久化
三个构造函数:分别是带容量的参数,无参,和带Collection参数的构造函数。
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); } } //构造容量是10的ArrayList public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //按collection 的 iterator传入 public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
给ArrayList瘦身,且和size一样大(size是已经使用的容量)。用Arrays.copyOf复制了已经使用的那部分组成一个新的数组相当于把尾巴多出的容量给剪掉了。
public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
扩容:可以看到默认扩充newCapacity是oldCapacity的1.5倍,如果传入了参数miniCapacity就会当成新的扩充容量,这里还考虑了整型上限问题,最多只能扩充到0x7fffffff。
//一些VM会占用头部字节,这里规定了最大上限,超过就会抛出OutOfMemoryError异常 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 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); }
在执行add()方法时,我们看到会调用这样一条方法
ensureCapacityInternal(size + 1);这个方法会将一个继承自AbastractList的mod变量自增1,该变量用来记录list长度被修改的次数在遍历时根据情况抛出异常;同时该方法会对ArrayList进行扩容,容量+1。
public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } private void ensureCapacityInternal(int minCapacity) b61f { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
同样addAll()也类似,扩容的容量取决于加入集合的长度:
public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
在执行add()或者remove()方法时,我们能看到底层调用的还是
void System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length);这个方法。对于数组如果删除的是中间的元素,那么后面的元素都要往前挪,同样的,增加中间的元素,后面的元素都要往后挪。
public E remove(int index) { rangeCheck(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; // clear to let GC do its work return oldValue; }
在这里通过调用clear()我们可以看到底层只是通过将元素置空,等待GC自动回收。
public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }
相关文章推荐
- Java - ArrayList源码分析
- java源码分析---ArrayList
- 【java集合】ArrayList源码分析
- java源码分析之ArrayList
- Java集合-ArrayList源码分析
- Java中ArrayList源码深入分析(JDK1.6)
- java源码分析之集合框架 ArrayList 03
- java基础解析系列(十)---ArrayList和LinkedList源码及使用分析
- Java ArrayList源码分析
- Java集合系列之ArrayList源码分析
- Java集合系列:-----------03ArrayList源码分析
- 【Java基础】Java学习之ArrayList源码常用方法分析
- Java集合源码分析(一)ArrayList
- Java集合之ArrayList源码分析
- java集合-ArrayList和源码分析
- java源码分析(13)-Arraylist
- Java ArrayList 源码分析
- java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析
- [Java代码] Java ArrayList源码分析
- 【深入Java基础】ArrayList源码分析