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