欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ArrayList源码分析(jdk11)

程序员文章站 2022-07-14 16:07:04
...

初始化方法:

    private static final int DEFAULT_CAPACITY = 10;//默认初始容量
    
     /**
     * 用户指定容量为0时返回数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    
     /**
     * 用户调用无参构造函数,在第一次添加元素时会以DEFAULT_CAPACITY扩容
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 保存数据,数组大小是arraylist的容量
     * transient:表示对象序列化时不包括该数组(writeObject()和readObject()实现对数组序列化和反序列化)
     * 原因:elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量,
     * 那么有些空间可能就没有实际存储元素,采用上诉的方式来实现序列化时,
     * 就可以保证只序列化实际存储的那些元素,而不是整个数组,从而节省空间和时间。
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * arraylist中实际大小(保存数据数量)
     */
    private int size;

    /**
     * 创建指定初始容量的空arraylist
     *
     * @param  initialCapacity 初始容量
     * @throws IllegalArgumentException 当初始容量小于0时抛异常
     */
    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);
        }
    }

    /**
     * 无参构造函数,在第一次加入元素时扩容至默认容量
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

  /**
     * 创建一个包含collection的ArrayList
     * @param c 要放入 ArrayList 中的集合,其内元素将会全部添加到新建的 ArrayList 实例中
     * @throws NullPointerException 当参数 c 为 null 时抛出异常
     */

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();//将集合转为数组
        if ((size = elementData.length) != 0) {//将数组长度赋值给size 并判断是否为0       
            if (elementData.getClass() != Object[].class)//如果数组不是objec[]t类型
                elementData = Arrays.copyOf(elementData, size, Object[].class);//将数组拷贝到object[]数组
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

扩容方法:

 /**  
     * 扩展ArrayList容量(提供给使用者的方法) :最好在 add 大量元素之前调用,以避免多次扩容
     */
    public void ensureCapacity(int minCapacity) {
        if (minCapacity > elementData.length
            && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                 && minCapacity <= DEFAULT_CAPACITY)) {
            modCount++;
            grow(minCapacity);
        }
    }

    /**
     * 可以分配数组的最大值
     * OutOfMemoryError: 申请数组大小超过vm限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
 * 数组扩容,当size等于数组长度并加入新数据时调用
 */
    private Object[] grow() {
        return grow(size + 1);
    }
    
    /**
     *数组扩容
     * @param minCapacity 指定最小容量
     * @throws OutOfMemoryError 最小容量小于0抛出异常
     */
    private Object[] grow(int minCapacity) {
        return elementData = Arrays.copyOf(elementData,
                                           newCapacity(minCapacity));//创建新数组,复制数据
    }



    /**
     * 返回扩容后的数组容量(1.5*oldCapacity)
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//数组原有的长度
        int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容后的长度,1.5*oldCapacity
        if (newCapacity - minCapacity <= 0) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)//如果当前数组为空
                return Math.max(DEFAULT_CAPACITY, minCapacity);//返回指定容量和默认容量的最大值
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return minCapacity;
        }
        return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);
    }
    /**
     * 当newCapacity超过MAX_ARRAY_SIZE时,调用此函数
     */
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE)
            ? Integer.MAX_VALUE
            : MAX_ARRAY_SIZE;
    }

常用方法:

   /**
     *返回arraylist长度
     */
   public int size() {
        return size;
    }
     /**
     *判断arraylist是否为空
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     *判断arraylist是否包含元素
     */
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

     /**
     *判断元素在arraylist中的索引,不存在返回-1
     */
    public int indexOf(Object o) {
        return indexOfRange(o, 0, size);
    }
     /**
     *判断元素在arraylist某一范围内的索引,不存在返回-1
     */
    int indexOfRange(Object o, int start, int end) {
        Object[] es = elementData;
        if (o == null) {
            for (int i = start; i < end; i++) {
                if (es[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = start; i < end; i++) {
                if (o.equals(es[i])) {
                    return i;
                }
            }
        }
        return -1;
    }
     /**
     *查找元素在arraylist中的最后出现的索引,不存在返回-1
     */
   public int lastIndexOf(Object o) {
        return lastIndexOfRange(o, 0, size);
    }
     /**
     *查找元素在arraylist中某一范围内最后出现的索引,不存在返回-1
     */
    int lastIndexOfRange(Object o, int start, int end) {
        Object[] es = elementData;
        if (o == null) {
            for (int i = end - 1; i >= start; i--) {//从数组末尾开始遍历
                if (es[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = end - 1; i >= start; i--) {
                if (o.equals(es[i])) {
                    return i;
                }
            }
        }
        return -1;
    }
 /**
     * 判断size与当前数组大小,如果相等则扩容数组
     */
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

未完。。。

System.arraycopy()与Arrays.copyOf():

Arrays.copyOf():

public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

在Arrays.copyOf()中调用了System.arraycopy()方法,参数为源数组和复制长度,方法自动创建目标数组,将源数组全部元素复制到目标数组并返回。

System.arraycopy():

public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

native方法,需要指定源数组、目标数组、起始索引和复制长度