Java集合深入学习 - ArrayList源码解析-1基础(基于jdk1.8)

Java集合深入学习 - ArrayList源码解析-1基础(基于jdk1.8)

Java集合深入学习 - ArrayList源码解析-2序列化与迭代器(基于jdk1.8)

Java集合深入学习 - ArrayList源码解析-3子List与坑点(基于jdk1.8)

1.类的定义

话不多说,直接上代码

/**
 * ArrayList 类定义  
 *      继承:AbstractList(抽象List) 
 *      实现:List,RandomAccess(支持快速随机访问标记),Cloneable(克隆),Serializable(序列化)
 */
public class ArrayList extends AbstractList
		implements List, RandomAccess, Cloneable, java.io.Serializable{}

/**
 * AbstractList类的定义 (抽象类)
 * 	继承:AbstractCollection(抽象集合)
 * 	实现:List
 */
public abstract class AbstractList extends AbstractCollection implements List{}

/**
 * AbstractCollection类定义(抽象类)
 * 	实现:Collection(集合接口)
 */
public abstract class AbstractCollection implements Collection{}

/**
 * Collection类定义(接口)
 * 	继承:Iterable(迭代器接口)
 */
public interface Collection extends Iterable {}

/**
 * Iterable类定义(接口)
 */
public interface Iterable{}

/**
 * List类定义(接口)
 * 	继承:Collection(集合接口)
 */
public interface List extends Collection{}


对应类关系如下图:

Java集合深入学习 - ArrayList源码解析-1基础(基于jdk1.8)_第1张图片

2.属性与构造方法

话不多说,直接代码中注释起来

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

	/** 默认的初始容量为10 */
    private static final int DEFAULT_CAPACITY = 10;
    /** 两个final的空数组 */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    /** 存放数据的数组 */
    transient Object[] elementData;
    /** 实际存放数据数量(并不是数组的大小) */
    private int size;

    /** 定义一个常量,含义为集合大小的最大值 */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
   
    /**
     * 初始化容量的构造方法
     * 	initialCapacity对应存放数据的数组的大小
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
        	//传入大小,直接初始化一个对应大小的数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        	//传入参数0 先默认数组为空数组,在第一次add的时候会初始化数组
            this.elementData = EMPTY_ELEMENTDATA;	
        } else {
        	//传入为负数时直接抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * 空参构造方法
     */
    public ArrayList() {
    	//默认数组为空数组,在第一次add的时候会初始化数组
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 给定集合入参的构造方法
     * 	知识点: 1.  String[].getClass() !=  Object[].class;
     * 	        2.子类重写父类方法的时候,若不修改返回值类型,则具体得到返回值的类型的是子类的返回值类型,而不会上转成父类的返回值类型
     */
    public ArrayList(Collection c) {
    	//直接获取集合中的数组(集合中的数据)
        elementData = c.toArray();
        //判断是否存在数据
        if ((size = elementData.length) != 0) {
        	//判断数据类型是否一致(传入集合的toArray方法可能被重写导致下面判断不成立)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
        	//无数据,数组置空
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
}

/** 父类属性 */
public abstract class AbstractList extends AbstractCollection implements List {
	/**
	 * 操作次数:指的是改变了list的长度大小或者使得遍历过程中产生不正确的结果的操作
	 * 	作用:在Iterator对数据进行迭代时用来判断数据是否发生了意外变化,导致最后遍历会失败
	 */
    protected transient int modCount = 0;
}

3.方法解析
  3.1 添加数据add的处理过程

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    /**
     * 添加数据
     */
    public boolean add(E e) {
    	//数组大小处理
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }
    
    /**
     * 数组大小处理
     */
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //第一次添加数据	返回数组大小
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    /**
     * 数组大小处理(是否需要扩容)
     */
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;	//操作次数+1
        if (minCapacity - elementData.length > 0)	//判断是否需要对数组进行扩容
            grow(minCapacity);	//扩容
    }
    
    /**
     * 对集合进行扩容
     */
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);	//newCapacity = 1.5 * oldCapacity 扩容到原大小的1.5倍
        //获取合适的大小
        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);	//数据copy,返回一个新的数组
    }
    
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) 
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

    /**
     * 在对应位置插入数据
     */
    public void add(int index, E element) {
        rangeCheckForAdd(index);	//校验下标
        
        //数组大小处理
        ensureCapacityInternal(size + 1);
        
        //数据后移(将从index位置开始往后数据都往后移动一位)
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = element;	//插入数据
        size++;
    }

    /**
     * 下标校验,判断下标是否超出大小
     */
    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;
    }

    /**
     * 添加集合中的全部数据到List中
     */
    public boolean addAll(Collection c) {
        Object[] a = c.toArray();	//获取数据
        int numNew = a.length;		//待添加数据数
        ensureCapacityInternal(size + numNew);  //本地数组大小处理
        System.arraycopy(a, 0, elementData, size, numNew);	//将获取到的数据添加到数组中
        size += numNew;		//集合size增加
        return numNew != 0;	//返回实际是否成功添加数据
    }
    
    /**
     * 将集合数据插入的List中(从指定下标开始插入)
     */
    public boolean addAll(int index, Collection 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);	//插入位置之后的数据整体向后移动numNew位

        System.arraycopy(a, 0, elementData, index, numNew);	//将数据从index位置开始插入到数组中
        size += numNew;	//集合size增加
        return numNew != 0;//返回实际是否成功添加数据
    }

  3.2 移除数据remove的处理过程

    /**
     * 下标校验,判断下标是否超出大小
     */
    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 E remove(int index) {
        rangeCheck(index);	//下标校验

        modCount++;		//操作次数+1
        E oldValue = elementData(index);	//获取待移除数据

        int numMoved = size - index - 1;	//计算需要移动的数据数
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);		//后边数据整体向前移动1位
        elementData[--size] = null; //最后一位置空

        return oldValue;
    }
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    
    /**
     * 移除指定数据(移除第一个) 返回操作是否成功,未找到对应数据返回false
     */
    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;	//未找到对应数据返回false
    }

    /**
     * 移除指定下表数据
     */
    private void fastRemove(int index) {
        modCount++;	//操作次数+1
        int numMoved = size - index - 1;	//计算需要移动的数据数
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);	//后边数据整体向前移动1位
        elementData[--size] = null; //最后一位置空
    }

    /**
     * 移除指定集合中的所有数据
     */
    public boolean removeAll(Collection c) {
        Objects.requireNonNull(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;	//获取List数据
        int r = 0, w = 0;
        boolean modified = false;	//是否成功移除数据
        try {
            for (; r < size; r++)	//遍历数据
                if (c.contains(elementData[r]) == complement)	//判断当前数据是否在指定集合中  是否符合条件complement
                    elementData[w++] = elementData[r];		//将满足条件的数据按顺序放到数组的前面
        } finally {
            if (r != size) {	//发现异常会进入到此条件
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);		//将还未处理数据直接放到最终数组之后
                w += size - r;					//计算满足条件数据大小
            }
            if (w != size) {	//判断是否有不满足条件数据  存在不满足条件数据时会进入此条件
                for (int i = w; i < size; i++)	//清空数组后面的无用数据(满足条件数据都已放到数组的前面,w之后的数据都是无用数据)
                    elementData[i] = null;
                modCount += size - w;	
                size = w;	//重新计算大小
                modified = true;	//标记有数据被处理掉
            }
        }
        return modified;	//返回是否有数据被处理掉
    }

  3.3 获取数据get与修改数据set以及其他方法

    @SuppressWarnings("unchecked")
    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);	//获取源
        elementData[index] = element;		//修改数据
        return oldValue;	//返回源数据
    }

    /**
     * 获取数据在集合里的下标(数据在集合中第一次出现)
     * 	存在返回对应下标,不存在返回-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;
    }

    /**
     * 获取数据在集合里的下标(数据在集合中最后一次出现)
     * 	存在返回对应下标,不存在返回-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 boolean isEmpty() {
        return size == 0;
    }

    /**
     * 集合中是否包含这个数据
     */
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
    /**
     * 将数组的大小设置为当前集合的大小(完成操作之后  数组大小=集合大小)
     */
    public void trimToSize() {
        modCount++;	//操作次数加一
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA	//size为0  数组置为空
              : Arrays.copyOf(elementData, size);	//获取数组的前size个数据,返回一个新的数组
        }
    }

    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            ? 0
            : DEFAULT_CAPACITY;
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    /**
     * 集合克隆,复制出一个新的集合与该集合数据完全一致,集合中数组大小为数据量大小
     */
    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);
        }
    }
    /**
     * 将集合转换成数组,数组的大小为集合数据量大小
     * 	返回一个新的Object[]
     */
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    /**
     * 将集合转换成数组,数组的大小为集合数据量大小
     * 	返回传入的数组
     */   
    @SuppressWarnings("unchecked")
    public  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;
    }

本文连接,转载请标注https://blog.csdn.net/luo_mu_hpu/article/details/106076965

你可能感兴趣的:(Java集合深入学习 - ArrayList源码解析-1基础(基于jdk1.8))