Java1.8中ArrayList源码分析

转载请注明原文地址:  http://zk-chs.iteye.com/blog/2250804

 

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

上面是是ArrayList类的定义,它继承了抽象类AbstractList,但是真正继承的方法只有equals和hashCode,

别的方法在ArrayList 中都有自己的重新实现;

 

List接口在AbstractList中已经实现,这里是为了表明一下,没有太大含义;

 

RandomAccess没有方法,表明ArrayList支持快速随机访问;

 

实 现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制,如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常;

 

类通过实现 java.io.Serializable 接口以启用其序列化功能,未实现此接口的类将无法使其任何状态序列化或反序列化

 

 

transient Object[] elementData; // 我们用于存储数据的数组
private static final int DEFAULT_CAPACITY = 10;  // 默认大小为10
private static final Object[] EMPTY_ELEMENTDATA = {}; 
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private int size; // elementDate中对象数量,不是length
protected transient int modCount = 0; // 用于并发使用

 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) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
EMPTY_ELEMENTDATA在使用带参数构造函数时使用;
DEFAULTCAPACITY_EMPTY_ELEMENTDATA在使用默认构造函数时使用;
DEFAULT_CAPACITY会在默认构造函数实例的第一次调用add方法时使用;
modCount:当迭代时,如果modCount发生了变化,那么抛出并发修改异常(ConcurrentModificationException);
 
关于ArrayList的域就介绍这么多,下面看看方法:
public boolean add(E e):
// 在当前列表末尾添加一个对象,而不是数组
public boolean add(E e) {
        // 确认数组大小,并让modCount + 1
        ensureCapacityInternal(size + 1);  // Increments modCount!!  
        elementData[size++] = e;
        return true;
    }

// if判断用于第一次调用add,如果是使用无参构造函数,那么进入此方法,设置minCapacity为10
private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // first add
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

// modCount自增,并判断数组大小是否足够,不够的话将增大数组(下面介绍grow)
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // 判断数组大小是否足够
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
 
private void grow(int minCapacity):这是private方法,不能使用
private void grow(int minCapacity) { // 传入需要的数组大小
        // oldCapacity为当前数组大小
        int oldCapacity = elementData.length; 
        // 设置新数组大小的值,为当前的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1); 
        // 当addAll时可能新数组大小也不够
        if (newCapacity - minCapacity < 0) 
            newCapacity = minCapacity;
        // newCapacity可能会溢出,这里做判断
        if (newCapacity - MAX_ARRAY_SIZE > 0) // MAX_ARRAY_SIZE = 2147483639
            newCapacity = hugeCapacity(minCapacity);
        // 使用Arrays扩展数组至newCapacity
        elementData = Arrays.copyOf(elementData, newCapacity); 
    }

private static int hugeCapacity(int minCapacity) { 
        if (minCapacity < 0) // overflow  溢出  抛出异常
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :  //2147483647
            MAX_ARRAY_SIZE; // 2147483639
    }
 
public boolean addAll(Collection<? extends E> c):
public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray(); // 传入集合的数组显示
        int numNew = a.length; 
        ensureCapacityInternal(size + numNew);  // 同上
        // 将a的numNew长度的元素添加到elementDate的末尾
        System.arraycopy(a, 0, elementData, size, numNew); 
        size += numNew; // 对象数量增长numNew
        return numNew != 0; // 如果c刚刚创建没有调用add,那么numNew会为0
    }
 
public void add(int index, E element)  和  public boolean addAll(int index, Collection<? extends E> c):
// 从指定索引位置插入元素
public void add(int index, E element) {
        rangeCheckForAdd(index); // 判断插入位置是否越界
        
        // 和add没什么不同
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 这就是我们常说的后移一位,其实是从指定位置开始复制
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

// 同上
public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index); // 判断插入位置是否越界

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

// 用于add和addAll  判断传入的索引值index是否越界
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
  需要注意:不管addAll添加多少元素,modCount只会自增1!!!
 
public E get(int index):
public E get(int index) { // 获取指定位置元素
        rangeCheck(index); // 注意  这里不是rangeCheckForAdd,下面介绍

        return elementData(index);
    }
 
public E set(int index, E element):
// 替换指定索引位置的元素,返回原位置元素
public E set(int index, E element) {
        rangeCheck(index); 

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
 
public E remove(int index): 已经申请的内存空间不会回收(删除指定索引位置元素)
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); // 相当于index+1后的元素前移一位
        elementData[--size] = null; // clear to let GC do its work 通知jvm回收,防止内存泄漏

        return oldValue; // 返回从list中移除的元素
    }

// 这里仅与size比较,小于0数组本身会抛异常
private void rangeCheck(int index) {
        if (index >= size) // 防止index在size与elementDate.length之间
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

// 返回索引位置元素
E elementData(int index) {
        return (E) elementData[index];
    }
 
public boolean remove(Object o):(删除指定元素)
// 通过遍历数组删除指定元素
public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index); // 快速删除
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

// 为什么叫fastRemove?因为不需要再做检查,后面与remove相同
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
    }
 
public void trimToSize():
// 将当前列表大小修改为当前元素size大小,释放被占用的空间
public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size); // 复制size个元素,即数组大小变成size
        }
    }
 
public int size()  和  public boolean isEmpty():
public int size() {
        return size; // 直接返回size
    }

public boolean isEmpty() {
        return size == 0;
    }
 
public boolean contains(Object o):
// 是否包含指定元素,
public boolean contains(Object o) {
        return indexOf(o) >= 0; // indexOf下面介绍
    }
 
public int indexOf(Object o)  和  public int lastIndexOf(Object o):
/**
 *  一个从前向后遍历,一个从后向前遍历
 */

public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
 
public Object clone():
// 为浅拷贝,不会拷贝数组内元素,两个列表引用相同的元素
public Object clone() { 
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) { // 实现了Cloneable就不会出现
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }
 
public Object[] toArray():
// 返回一个复制的数组,大小为size,而不是elementData.length,含有elementData中所有元素
public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }
 
public <T> T[] toArray(T[] a):
// 传入一个指定类型的数组
public <T> T[] toArray(T[] a) {
        if (a.length < size) // 如果a长度小于size,那么直接复制elementData,大小为size
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        // 否则从a的0索引开始复制,而且a[size]会被设置为null !!!!!
        // 如果你的数组很重要,那就小心点这个方法
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }
 
 public void clear():
// 清空当前列表,但是已经申请的空间大小(elementData.length)不会变
public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }
 
public void ensureCapacity(int minCapacity):
// 保证当前列表至少有minCapacity的大小
public void ensureCapacity(int minCapacity) {
        // minExpand为0或为10
        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);
        }
    }

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
 
protected void removeRange(int fromIndex, int toIndex):
protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex; // 要移动的元素数量
        // 将从toIndex开始,共numMoved个元素移动到fromIndex的位置
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        // 移除范围内元素后新的size大小
        int newSize = size - (toIndex-fromIndex);
        // 将复制的多余的数组空间设置为空,使gc可以回收,防止内存泄漏
        for (int i = newSize; i < size; i++) { 
            elementData[i] = null;
        }
        size = newSize;
    }
 
 public boolean removeAll(Collection<?> c)  和  public boolean retainAll(Collection<?> c):
// 删除所有与c中任一对象相同的对象,从下面到contains我们能知道是调用equals比较
public boolean removeAll(Collection<?> c) {
        // 判断是否为空,为空抛出空指针
        Objects.requireNonNull(c); 
        return batchRemove(c, false);
    }

// 保留所有与c中任一对象相同的对象
public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

// 批量删除,不建议使用,contains每次都要遍历,效率低下
private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                // contains每次都要遍历
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            // finally语句块,即使contains抛出异常也会执行
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }
 
public List<E> subList(int fromIndex, int toIndex):
public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size); // 常规的判断,见下
        return new SubList(this, 0, fromIndex, toIndex); // 内部类SubList,后面介绍
    }

static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > size)
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
    }
 
下面看看内部类SubList
private class SubList extends AbstractList<E> implements RandomAccess
 除了是private没什么特别的
// 接着是域和构造函数,传入的list作为parent引用的对象
        private final AbstractList<E> parent;
        private final int parentOffset;
        private final int offset;
        int size;

        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex; // 截取的新列表的元素数量
            this.modCount = ArrayList.this.modCount; 
        }
 可以看到sublist的所有状态都是与传入的parent相关的;
如果你看了sublist的源码的话,你会发现它操作的就是parent的elementData数组;
只是每个方法添加了个offset而已,方法内容都是一样的,这里就不再重复了;
 
ArrayList的迭代器有2种;分别是Itr和ListItr;
private class Itr implements Iterator<E>
private class ListItr extends Itr implements ListIterator<E>
List比Itr多了操作对象的方法(例如add,set,previous等等);
下面是调用迭代器的方法:
// ListIterator支持从指定索引开始迭代
public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }


public ListIterator<E> listIterator() {
        return new ListItr(0);
    }


public Iterator<E> iterator() {
        return new Itr();
    }
 
多看集合容器源码对于我们理解和使用容器是很有好处的,而且可以更好的在编写并发代码
并发处理一定要良好的运用各个集合容器,以及扩展的concurrent下的线程安全容器(并非一定安全)
如果仅仅使用像vector一样的全部方法synchronized的集合的话,那么效率会非常低;
跑题了,希望能够一起进步吧...

你可能感兴趣的:(Java1.8中ArrayList源码分析)