JDK8 ArrayList源码解析

xiaoxiao2021-02-28  57

1.属性及构造方法

/**序列化id**/ 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; //默认构造方法 public ArrayList() { //默认构造方法只是简单的将 空数组赋值给了elementData this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //带初始容量的构造方法 public ArrayList(int initialCapacity) { //如果初始容量大于0,则新建一个长度为initialCapacity的Object数组. if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) {//如果容量为0,直接将EMPTY_ELEMENTDATA赋值给elementData this.elementData = EMPTY_ELEMENTDATA; } else {//容量小于0,直接抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //利用别的集合类来构建ArrayList的构造函数 public ArrayList(Collection<? extends E> c) { //直接利用Collection.toArray()方法得到一个对象数组,并赋值给elementData elementData = c.toArray(); //因为size代表的是集合元素数量,所以通过别的集合来构造ArrayList时,要给size赋值 if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class)//这里是当c.toArray出错,没有返回Object[]时,利用Arrays.copyOf 来复制集合c中的元素到elementData数组中 elementData = Arrays.copyOf(elementData, size, Object[].class); } else { //如果集合c元素数量为0,则将空数组EMPTY_ELEMENTDATA赋值给elementData this.elementData = EMPTY_ELEMENTDATA; } }

2.add(E e)

public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e;//在数组末尾追加一个元素,并修改size return true; } public void add(int index, E element) { rangeCheckForAdd(index);//越界判断 ensureCapacityInternal(size + 1); System.arraycopy(elementData, index, elementData, index + 1, size - index);//将index开始的数据 向后移动一位 elementData[index] = element; size++; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//使用默认构造函数,设置容量10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;//modCount表示修改集合的次数 if (minCapacity - elementData.length > 0) grow(minCapacity); } 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);//拷贝到新长度的数组 }

3.remove(int index)

public E remove(int index) { rangeCheck(index);//判断是否越界 modCount++;//修改modeCount 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 //置空原尾部数据,GC掉 return oldValue; }

4.get(int index)

//一看便知 public E get(int index) { rangeCheck(index); return elementData(index); }

5.clear()

public void clear() { modCount++;//修改modCount // clear to let GC do its work for (int i = 0; i < size; i++) //遍历置空 elementData[i] = null; size = 0; //修改size }

6.set(int index, E element)

public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index);//取出要改的元素 elementData[index] = element;//覆盖旧元素 return oldValue; }

7.总结

扩容条件:将当前size+1和数组长度比较,前者大则引发扩容,每次add都有这步判断改和查只是覆盖元素或返回元素,速度快;删和加会触发数组copy,速度慢;
转载请注明原文地址: https://www.6miu.com/read-2627520.html

最新回复(0)