ArrayList源码分析(jdk-8)

类及继承关系

public class ArrayList<E> extends AbstractList<E> 
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable复制代码

implemnts RandomAccess表明了其拥有随机快速访问的能力,能够根据下标快速访问元素java

ArrayList底层是数组,会占据连续的内存空间(数组的长度>真正数据的长度), 数组的缺点:空间效率不高。 

当添加元素,超出现有数组容量时,便会进行扩容操做:

ArrayList的增加因子1,扩容1/2复制代码
public void ensureCapacity(int minCapacity) {//设定初始容量的构造函数
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)        
           // any size if not default element table 
           ?0   
           // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); }} //如下三个方法实现了Array扩容的操做 private void ensureCapacityInternal(int minCapacity) { 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); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容容量为旧容量的1.5倍,增加因子为1/2 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);//此方法最总会调用System.ArrayCopy() } public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } //System类中的静态方法,这是一个native方法. //经过此方法实现复制出新数组,实现数组的扩容(其是对对象引用的复制-浅度复制) public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)复制代码

成员变量

int modCount: 每次数组结构改变都会modCount++(增长致使扩容,或者删)数组

private int size; 集合数据的长度-list.size()获取的值bash

transient Object[] elementData;真正的存储东西的元素数组. 长度会>= sizedom

修饰词:transient,不参与序列化。 通常数组的容量会大于所存元素的个数,因此不必所有参与序列化,浪费多余空间.在writeObject()中序列化真正存储数据的元素就能够了.复制代码

增,删,改,查

数组的结构改变标识为modCount的值改变了ide

System.arraycopy()是一个native的数组之间复制的操做,由集合中的grow(minCapacity) 方法控制函数

👇是ArrayList的增删改查方法里,☝两个关键数据的变化的状况ui

##1.增---public boolean add(E e)

`modCount++
if (minCapacity - elementData.length > 0)`----若是新集合长度>如今数组长度 会`grow(minCapacity)`;复制代码

##2.删---remove(Object o)this

`modCount++
grow(minCapacity);`复制代码

##3. 改---set(int index, E element)spa

两个操做都没发生复制代码

##4.查---contains(Object o) ,indexOf(Object o)code

两个操做都没发生复制代码

迭代器

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;//将modCount的值记录下来
    public boolean hasNext() {
        return cursor != size;
    }
    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();//每次都会先检查是否发生过结构改变(modCount值是否相同)
        int i = cursor;
        if (i >= size)            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();
        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }}复制代码

总结

增,删,改,查等每次都会先检查是否索引越界
增删数组确定会修改modCount的值
System.arrayCopy()发生条件:a集合增长致使扩容,b删除元素。而集合的改查不会发生数组拷贝
结合安卓加载数据使用场景, 列表展现经常使用,查是高频操做,增删较少,因此ArrayList最合适 复制代码

zyt

相关文章
相关标签/搜索