Java源码解析之———ArrayList

    ArrayList是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。继承于AbstractList,实现了List,RandomAccess,Cloneable,java.io.serializable这些接口。

    和Vector不同,ArrayList中的操作不是线程安全的!!!所以建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。

    继承关系如图

java.lang.Object
   ↳     java.util.AbstractCollection<E>
         ↳     java.util.AbstractList<E>
               ↳     java.util.ArrayList<E>

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

    ArrayList包含了两个重要的对象:elementData和size

    (1)、elementData是Object类型的数组,它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数ArrayList(int initalCapacity)来执行它的初始容量为initalCapaccity;如果通过无参构造创建ArrayList 那么elementData默认容量为10。此数组的大小会根据ArrayList容量的增长而动态的增长,具体的增长方式,在ensureCapacity()方法中。

    (2)、size就是动态数组的实际大小


构造函数

    Arraylist 提供了三种方式的构造器,可以构造一个默认初始容量为10 的空列表,构造一个制定初始容量的空列表以及构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回的顺序排列的。

    

**
     * 构造一个指定初始容量的空列表
     * @param  initialCapacity  ArrayList的初始容量
     * @throws IllegalArgumentException 如果给定的初始容量为负值
     */
    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的空列表
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回的顺序排列的
     * @param c 包含用于去构造ArrayList的元素的collection
     * @throws NullPointerException 如果指定的collection为空
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray()可能不会正确地返回一个 Object[]数组,那么使用Arrays.copyOf()方法
            if (elementData.getClass() != Object[].class)
                //Arrays.copyOf()返回一个 Object[].class类型的,大小为size,元素为elementData[0,...,size-1]
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

此处说一下,ArrayList是如何创建一个默认初始容量为10的列表的。

在jdk1.6中 构造函数是这样的

public ArrayList() {    
    this(10);  //public ArrayList(int initialCapacity)中this.elementData = new Object[initialCapacity];
}

而之后的版本做了更改分为以下几步

1、初始情况:elementData=DEFAULTCAPACITY_EMPTY_EMEMENTDATA= {} ; // 此时size = 0

2、当我们向集合中新加一个元素的时候调用add方法会调用ensureCapacityInternal(size + 1) 方法,也就是ensureCapacityInternal(1) 

3、在ensureCapacityInternal(int minCapacity) 方法中,当数组为空时,可得的minCapacity=DEFAULT_CAPACITY= 10,然后再调用ensureExplecitCapacity(minCapacity) 方法,即ensureExplicitCapacity(10);

4、在ensureExplicitCapacity(minCapacity)方法中调用grow(minCapacity)方法,也就是grow(10) ,这就是真正具体的数组扩容方法,在这里,通过elementData = Arrays.copyOf(elementData,10)实现了elementData数组初始容量为10的构造

/**
     * public方法,让用户能手动设置ArrayList的容量
     * @param   minCapacity 期望的最小容量
     */
    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);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        //当elementData为空时,ArrayList的初始容量最小为DEFAULT_CAPACITY(10)
        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);
    }

    //数组可被分配的最大容量;当需要的数组尺寸超过VM的限制时,可能导致OutOfMemoryError
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 增加数组的容量,确保它至少能容纳指定的最小容量的元素量
     * @param minCapacity 期望的最小容量
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //注意此处扩充capacity的方式是将其向右一位再加上原来的数,实际上是扩充了1.5倍
        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);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }


//将指定元素添加到集合中
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
//将指定元素添加到集合的指定位置
public void add(int index, E element) {
        //判断传入索引是否符合规范
        rangeCheckForAdd(index); 

        //如果数组长度不够 , 将进行扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!  
        //从index 开始 将所有元素的位置向后移动一位
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index); 
        elementData[index] = element;
        size++;
    }
//按照collection的迭代器返回的元素顺序,将所有元素添加到集合的尾部
public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        //将数组a[0,...,numNew-1]复制到数组elementData[size,...,size+numNew-1]
        System.arraycopy(a, 0, elementData, size, numNew); 
        size += numNew;
        return numNew != 0;
    }
//从index开始将collection中所有元素添加到集合后面

public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index); //判断参数index是否IndexOutOfBoundsException

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

        int numMoved = size - index;
        if (numMoved > 0)
            //先将数组elementData[index,...,index+numMoved-1]复制到elementData[index+numMoved,...,index+2*numMoved-1]
            //即,将源数组中从index位置开始的后numMoved个元素统一后移numNew位
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
        //再将数组a[0,...,numNew-1]复制到数组elementData[index,...,index+numNew-1]
        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }
//删除指定索引的元素
public E remove(int index) {
        //判断传入索引的合法性
        rangeCheck(index);  

        modCount++;
        E oldValue = elementData(index);
        //将数组中index之后的所有元素向前移动一位
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //将原数组最后一个元素滞空,方便gc清理
        elementData[--size] = null; 

        return oldValue;
    }
//删除集合中指定元素(第一个),Arraylist中允许存储重复元素
public boolean remove(Object o) {
    // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。
    if (o == null) {
        or (int index = 0; index < size; index++)
        if (elementData[index] == null) {
          //集合内部私有的删除方法 不校验index 也没有返回值
           fastRemove(index);
           return true;
        }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
               fastRemove(index);
               return true;
            }
       }
     return false;
    }

//集合内部私有的删除方法 不校验index 也没有返回值
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 clear() {

    modCount++;

    //将数组中所有元素制空
    for (int i = 0; i < size; i++)
        elementData[i] = null;

        size = 0;
    }
}
//删除从fromIndex 到toIndex 之间的元素 包左不包右
protected void removeRange(int fromIndex, int toIndex) {

        modCount++;
        //需要向前移动的元素的个数  共删除toIndex - fromIndex个元素
        int numMoved = size - toIndex;  
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }
 
 
//删除集合中包含c中元素的元素
public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);  //检查指定的对象c是否为空
        return batchRemove(c, false);
    }
//删除集合中不包含在c中元素的所有元素  与removeAll()相反
public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c); 
        return batchRemove(c, true);
    }
 
 
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++)
                //判断中 是否包含elementData[r]元素
                if (c.contains(elementData[r]) == complement) 
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            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;
    }
//将index索引的元素替换为element
public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
//判断集合中是否包含o元素
 
 
public boolean contains(Object o) {
        //如果不存在返回-1  就返回false
        return indexOf(o) >= 0;
    }
//正向查找,返回o元素在集合中第一次出现的索引  如果不存在 返回-1
 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;
    }
//逆向查找 ,返回o元素在集合中最后一次出现的索引 , 如果不存在返回-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;
    }

 
 
@SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

//返回index索引处的元素
 public E get(int index) {
        //校验索引是否符合标准
        rangeCheck(index);
        return elementData(index); 
    }
//将elementData数组的容量调整为当前集合中元素的size
 
 
public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }
//返回元素的个数
public int size() {
        return size;
    }
//判断集合是否为空
 
 
public boolean isEmpty() {
        return size == 0;
    }
//因为ArrayList 实现了Cloneable,所以有拷贝功能
public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }
//返回一个包含所有元素的数组
public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }
 
 
//如果a的长度足够,则将所有的集合中所有元素存放于a数组中,并返回
//如果a的长度不够,将新生成一个数组,长度等同于集合的长度,将所有元素存放于此数组中
@SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }
 
 
 
 
 
 


猜你喜欢

转载自blog.csdn.net/java_ying/article/details/79962198