ArrayList

作者: 汤姆torn | 来源:发表于2020-06-13 11:44 被阅读0次

    Java ArrayList源码学习(学习记录,可能有很多理解不对的地方,大佬勿喷,谢谢)

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
    /*
    *是当对象序列化的时候对象的一个标识,作用是序列化时转化为byte流,还能反序列化成原始类,主要用于版本控制
    */
    private static final long serialVersionUID =8683452581122892189L;
    
    /*
    * 默认初始容量为10
    */
    private static final int DEFAULT_CAPACITY = 10;
    
    /*
    * 空数组,在调用无参构造方法时默认是这个空数组
    */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    
    /*
    * 用于保存数据的数组
    */
    private trainsient Object[] elementData;、
    
    /*
    * 元素的数量
    */
    private int size;
    
    /*
    * 通过构造方法传入默认容量设置数组大小
    */
    public ArrayList(int initialCapacity) {
            if (initialCapacity > 0) {  //大于0新生成一个容量为传入参数的数组
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) { //等于0时生成空数组
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            }
        }
    
    /*
    * 默认生成空的数组
    */
     public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    
    /*
    * 把传入的集合中的值复制到arryList里
    */
    public ArrayList(Collection<? extends E> c) {
            elementData = c.toArray();                //c转为数组后传递给arayList
            if ((size = elementData.length) != 0) { //如果长度不等于0
                if (elementData.getClass() != Object[].class)   //如果两者的类型不一致
                    elementData = Arrays.copyOf(elementData, size, Object[].class);  //把传入的数组赋给arrayList数组
            } else { //如果长度等于0,生成空数组
                this.elementData = EMPTY_ELEMENTDATA;  
            }
        }
    
    /*
    *  实际尺寸
    */
    public void trimToSize() {
            modCount++; ///定义于ArrayList的父类AbstractList,用于存储结构修改次数
            if (size < elementData.length) { // 如果arrayList长度小于数组长度
                elementData = (size == 0)       //数据数组长度是否为0?空数组:复制数组数据和长度
                  ? EMPTY_ELEMENTDATA
                  : Arrays.copyOf(elementData, size);
            }
        }
    
    /*
    *   确保容量容纳得下数据
    */
    public void ensureCapacity(int minCapacity) { //所需最小的容量
            int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                ? 0 : DEFAULT_CAPACITY;    //如果 arrayList数据不为空数组?0 :默认值10
    
            if (minCapacity > minExpand) 
                ensureExplicitCapacity(minCapacity);  
            }
        }
    
    /*
    *   计算容量
    */
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果为空
                return Math.max(DEFAULT_CAPACITY, minCapacity);  //返回默认容量和最小容量比较大那个
            }
            return minCapacity;
        }
    
    
    /*
    *  确保装得下
    */
    private void ensureCapacityInternal(int minCapacity) { 
            ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
        }
    
    
     private void ensureExplicitCapacity(int minCapacity) { 
            modCount++;      //动态增长时的数
     
            if (minCapacity - elementData.length > 0)  如果最小容量比arrayList的容量大
                grow(minCapacity);            //增长minCapacity
        }
    
    /*
    *  数组扩充容量
    */
     private void grow(int minCapacity) {
            // overflow-conscious code
            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); //把元素和新容量赋给arrayList
        }
    
    private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0)  
                throw new OutOfMemoryError();
            return (minCapacity > MAX_ARRAY_SIZE) ?  //最小容量是否超过最大容量?integer最大值:integer最大值-8
                Integer.MAX_VALUE :                
                MAX_ARRAY_SIZE;  
        }
    
    /*
    * 最大的数组容量,在jvm中获取数组长度使用了arraylength字节码指令,
    * 长度8是用来记录字节码指令的,并不固定是8,为了减少内存溢出(OOM)
    */
     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
    /*
    * 长度
    */
    public int size() {
            return size;
        }
    
    /*
    * 是否为空
    */
    public boolean isEmpty() {
            return size == 0;
        }
    
    /*
    * 是否包含某个元素
    */
    public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    
    /*
    * 获得元素索引
    */
    public int indexOf(Object o) {
            if (o == null) {     //如果为null,遍历数组,查询为null的下标,找到返回下标
                for (int i = 0; i < size; i++)
                    if (elementData[i]==null)
                        return i;
            } else {            //如果元素不为null,遍历,如果找到返回下标
                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;
        }
    
    /*
    * 复制,返回数组实体,无值
    */
    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);
            }
        }
    
    /*
    *  调用arrays的数组方法
    */
    public Object[] toArray() {
            return Arrays.copyOf(elementData, size);
        }
    
    
    /*
    * 如果列表适合指定数组,返回它,否则,创建一个新数组,分配
    *指定数组的运行时类型和大小
    */
    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;
        }
     
    /*
    * 根据索引获得元素值
    */
     E elementData(int index) {
            return (E) elementData[index];
        }
    
    /*
    *  检查索引范围,返回元素值
    */
    public E get(int index) {
            rangeCheck(index);
    
            return elementData(index);
        }
    
    /*
    *  替换值
    */
     public E set(int index, E element) {
            rangeCheck(index);    //检查范围
    
            E oldValue = elementData(index);  //把索引为index的值得到
            elementData[index] = element;  //把元素设置到该位置
            return oldValue;
        }
    
    /*
    *  添加element
    */
     public boolean add(E e) {
            ensureCapacityInternal(size + 1);  //扩充长度
            elementData[size++] = e;    //插入在末尾
            return true;
        }
    
    /*
    *  根据索引添加element
    */
     public void add(int index, E element) {
            rangeCheckForAdd(index);   //检查是否在范围内
    
            ensureCapacityInternal(size + 1);  //扩充
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);     //复制指定的源数组的数组,把elementData中从index开始以后的元素复制到elementData的index+1的位置上,个数为size-index个
    
            elementData[index] = element; //将elementData下边index位置赋值目标值
            size++;   //arrayList+1
        }
    
    
    
    /*
    *  根据索引删除element
    */
    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);              //把elementData中,index后的元素复制到数组中
            elementData[--size] = null;  
            return oldValue;
        }
    
    
    /*
    *  删除元素,同 add
    */
    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;
        }
    
    /*
    *   删除元素
    */
     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;  // 数组前移一位,size自减,空出来的位置置null,具体的对象的销毁由Junk收集器负责
        }
    
    
     public void clear() {
            modCount++;
            for (int i = 0; i < size; i++)            
                elementData[i] = null;       清空数组,设置长度为0
            size = 0;
        }
    
    /*
    * 把集合添加进arrayList
    */
    
     public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();            //把C变成数组
            int numNew = a.length;            //获取数组长度
            ensureCapacityInternal(size + numNew);      //增加操作数
            System.arraycopy(a, 0, elementData, size, numNew);  //把新的数组复制到elementData中
            size += numNew;                         //更改elementData长度
            return numNew != 0;
        }
    
    /*
    * 在指定的索引后添加集合
    */
     public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);   
    
            Object[] a = c.toArray();
            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); //把集合放入elementData中
            size += numNew;
            return numNew != 0;
        }
    
    
    /*
    * 删除索引之间的元素
    */
    protected void removeRange(int fromIndex, int toIndex) {
            modCount++;
            int numMoved = size - toIndex;         //需要移动的元素是删除元素后的元素
            System.arraycopy(elementData, toIndex, elementData, fromIndex,
                             numMoved);           将elementData从toIndex位置开始的元素向前移动到fromIndex
            // clear to let GC do its work
            int newSize = size - (toIndex-fromIndex);
            for (int i = newSize; i < size; i++) {
                elementData[i] = null;          //把toIndex后的元素置空
            }
            size = newSize;     
        }
    
    
     private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
     private void rangeCheckForAdd(int index) {
            if (index > size || index < 0)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
    private String outOfBoundsMsg(int index) {
            return "Index: "+index+", Size: "+size;
        }
    
    /*
    *  删除集合
    */
      public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);     //判断c是否为空
            return batchRemove(c, false);
        }
    
    /*
    *  保留集合
    */
    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;               //w为write,r为read
            boolean modified = false;         
            try {
                for (; r < size; r++)
                    if (c.contains(elementData[r]) == complement) ; //若保留,就将相同元素移动到前段,不删除,就将不同元素移动到前段
                        elementData[w++] = elementData[r];     //将原数组的r位置的数据覆盖掉w位置的数据,r位置的数据不变,并其w自增,r自增。        
            } finally { 
                if (r != size) {   //确保异常抛出前的部分可以完成期望的操作,未遍历的部分会接到后面
                    System.arraycopy(elementData, r, 
                                     elementData, w,
                                     size - r);                  
                    w += size - r;      
                } 
                if (w != size) {         //如果w == size ,表示全部元素被保留,那么没有删除操作,所以返回false,反之,返回true,没有删除操作。当w != size的时候,即使抛出异常,也能正确处理抛出前的操作,所以w始终为保存的前段部分
                    for (int i = w; i < size; i++)
                        elementData[i] = null;                 
                    modCount += size - w;
                    size = w;      //新的大小为保留元素个数
                    modified = true;
                }
            }
            return modified;
        }
    
    }
    
    
    

    相关文章

      网友评论

        本文标题:ArrayList

        本文链接:https://www.haomeiwen.com/subject/wtlatktx.html