容器 - ArrayList源码解析

构造方法

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    	private static final long serialVersionUID = 8683452581122892189L;

    	private static final int DEFAULT_CAPACITY = 10;         	//默认初始容量大小	
   		private static final Object[] EMPTY_ELEMENTDATA = {};   // 空数组(用于空实例)当用户指定 ArrayList 容量为0 时,返回该空数组。	

	    // 当用户没有指定 ArrayList 的容量时(即调用无参构造函数),返回的是该数组
	    // 刚创建一个 ArrayList 时,其内数据量为0,用户第一次添加元素时,该数组扩容,变成默认容量为10(DEFAULT_CAPACITY) 的一个数组
    	private static final Object [] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

     	// 保存ArrayList数据的数组,避免java自带的序列化机制,可用writeObject和readObject读写
    	transient Object [] elementData; 
 		private int size;    
		protected transient int modCount = 0;   // 用来实现fail-fast机制的

	    // 带初始容量参数的构造函数。(用户自己指定容量)
	 	public ArrayList(int initialCapacity) {
	        	if (initialCapacity > 0) {
	            	    //创建initialCapacity大小的数组
	            		this.elementData = new Object[initialCapacity];
	       		 } else if (initialCapacity == 0) {
	            		//创建空数组
	            		this.elementData = EMPTY_ELEMENTDATA;
	       		 } else {
	            		throw new IllegalArgumentException("Illegal Capacity: "+   initialCapacity);
	        	}
	   	 }

	  	// 无参构造函数:创建一个空的 ArrayList,长度为 0,当元素第一次被加入时,扩容至默认容量 10
	    public ArrayList() {
	         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	    }
	
	     // 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
	    public ArrayList(Collection<? extends E> c){
	        	elementData = c.toArray();
	       		 if ((size = elementData.length) != 0) {
	           		 	// c.toArray 可能返回的不是Object [],所以加于判断,用到了反射里面的getClass()方法
	            		if (elementData.getClass() != Object[].class)
	                		elementData = Arrays.copyOf(elementData, size, Object[].class);
	       		} else {
	           		this.elementData = EMPTY_ELEMENTDATA;
	        	}
	    	}

	     // 将数组缓冲区大小调整到实际 ArrayList 存储元素的大小;     
	    public void trimToSize() {
			 	// 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的,该字段表示list结构上被修改的次数。
			   modCount++;     
			   // 如调用默认构造函数后,刚添加一个元素,此时 elementData.length = 10,而 size = 1,使得空间得到有效利用,减少资源浪费.
	           if (size < elementData.length) {
	                 elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);
	           }
	    }

		....
}

ArrayList的扩容机制

 //得到最小扩容量
private void ensureCapacityInternal(int minCapacity) {
    // 当 要 add 进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity 为10。
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity= Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}
   
 //判断是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);   
}

 // 数组缓冲区最大存储容量, 一些 VM 会在一个数组中存储某些数据--->为什么要减去 8 的原因
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);   //扩充当前容量的1.5倍
    if (newCapacity - minCapacity < 0)     
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)  
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

 // 私有方法:大容量分配,最大分配 Integer.MAX_VALUE
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) 
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

增加元素

 	// 增加指定的元素到ArrayList的最后位置
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount
        elementData[size++] = e;
        return true;
    }

    // 在这个ArrayList中的指定位置插入指定的元素,
    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++;
    }

    // 将一个集合的所有元素顺序添加(追加)到 list 末尾
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;     //要添加元素的个数
        ensureCapacityInternal(size + numNew);  //扩容
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    // 从 List 中指定位置开始插入指定集合的所有元素, list中原来位置的元素向后移,并不会覆盖掉在 index 位置原有的值
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        Object[] a = c.toArray();//是将list直接转为Object[] 数组
        int numNew = a.length;  
        ensureCapacityInternal(size + numNew);  

        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;
    }

  	// 添加时检查索引是否越界
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(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);
        elementData[--size] = null;
        return oldValue;
    }

    // 移除list中指定的第一个元素(符合条件索引最低的)
    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;
    }

    // 快速删除第 index 个元素,remove(int index)相比: 跳过检查,不返回被删除的值
    private void fastRemove(int index) {
        modCount++;//这个地方改变了modCount的值了
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index, numMoved);
        elementData[--size] = null; 
    }


    // 从此列表中删除所有索引为fromIndex (含)和toIndex之间的元素。
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;//要移动的数量
        System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);

        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

查找元素

 // 顺序查找,返回元素的最低索引值(最首先出现的索引位置)
    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;
    }

  // 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-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;
    }


     //  返回此ArrayList实例的浅拷贝。 (元素本身不被复制) 
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

     // 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 
    public Object [] toArray() {
        return Arrays.copyOf(elementData, size);
    }

  /**
     *  a 需要存储 list 中元素的数组
     * 若 a.length >= list.size,则将 list 中的元素按顺序存入 a 中,a 中原有元素会被 list 的元素覆盖,然后 a[list.size] = null, a[list.size + 1] 及其  		   后的元素依旧是 a 的元素
     * 否则,将返回包含list 所有元素且数组长度等于 list 中元素个数的数组
     */
    @SuppressWarnings("unchecked") //告诉编译器忽略 unchecked 警告信息。
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

    // 获取指定位置上的元素,从0开始
    public E get(int index) {
        rangeCheck(index);    //检查是否越界
        return elementData(index);
    }

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    // 返回在索引为 index 的元素:数组的随机访问

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

    // 设置 index 位置元素的值,替换原有的元素值。
    public E set(int index, E element) {
        rangeCheck(index);
        E oldValue = elementData(index);    //获取旧数值
        elementData[index] = element;
        return oldValue;
    }

序列化与反序列化

  	// 私有方法, 将ArrayList实例序列化
    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException{

        int expectedModCount = modCount;
        s.defaultWriteObject();  // 将当前类的非静态和非瞬态字段写入此流

        //写入clone行为的容量大小
        s.writeInt(size);

        //以合适的顺序写入所有的元素
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }

        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

    // 私有方法,从反序列化中重构ArrayList实例
    private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        //读出大小和隐藏的东西
        s.defaultReadObject();

        // 从输入流中读取ArrayList的size
        s.readInt(); // ignored

        if (size > 0) {
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // 从输入流中将“所有的元素值”读出
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值