ArrayList JDK1.8 源码学习

       ArrayList 就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了动态的增加和减少元素的方法,继承了AbstractList类,实现了List, RandomAccess, Cloneable, java.io.Serializable 接口。

一、静态变量

// 默认初始化动态数组的大小
private static final int DEFAULT_CAPACITY = 10;

// 定义一个空的动态数组,长度为0
private static final Object[] EMPTY_ELEMENTDATA = {};

// 定义一个空的动态数组,长度为默认大小,实际是在第一次添加元素时才在内存中开辟一块大小为 4字节*DEFAULT_CAPACITY 的空间
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// 动态数组默认最大长度,超过这个长度可能导致OutOfMemoryError
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

二、私有属性

// 存储数组列表元素的数组缓冲区。数组的容量是这个数组缓冲器的长度。当添加第一个元素时,任何带有elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空ArrayList将被扩展为DEFAULT_CAPACITY。
transient Object[] elementData; // non-private to simplify nested class access

// 动态数组包含元素的大小
private int size;

三、构造方法

1、 初始化一个大小为 initialCapacity 的动态数组,若initialCapacity==0,先顶一个空数组,然后在添加一个元素时开辟一块 4字节*DEFAULT_CAPACITY 大小的内存空间
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);
        }
    }

2、初始化一个空的动态数组,在添加一个元素时开辟一块 4字节*DEFAULT_CAPACITY 大小的内存空间
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

3、根据已有集合创建动态数组
    public ArrayList(Collection c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // 如果elementData的类不是Object[]时,重新复制一次。这是因为c.toArray()会有不同的类型
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

四、主要方法

1、添加一个元素
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 检查空间大小
        elementData[size++] = e;    //在数组的末尾添加元素
        return true;
    }
    
    // 检查动态数组的空间大小
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 如果 elementData 是一个空数组,在创建一个默大小的动态数组
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // 如果添加元素需要的最小空间大小 大于动态数组的实际大小,则需要扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    //扩容
    private void grow(int minCapacity) {
        // 第一次准备扩容原来大小的一般,若还不够,则扩容 添加元素实际所需的大小,若准备扩容的大小大于了动态数组的最大大小(MAX_ARRAY_SIZE),则需要hugeCapacity方法判断需要扩容多少
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        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);
    }
    
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        // 如果添加元素所需的大小 大于动态数组的最大大小(MAX_ARRAY_SIZE),则扩容到Integer.MAX_VALUE,否则扩容到MAX_ARRAY_SIZE;如果添加元素所需的大小大于Integer.MAX_VALUE,则会发生内存溢出错误。
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

2、在指定位置添加一个元素
    public void add(int index, E element) {
        //  检查添加元素的位置是否合理      
        rangeCheckForAdd(index);
        
        ensureCapacityInternal(size + 1);  // 检查动态数组的空间大小
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);    // 把指定位置及位置后面的元素各后移一位
        elementData[index] = element;    // 在指定位置添加一个元素
        size++;
    }
    
    private void rangeCheckForAdd(int index) {
        // 如果指定的位置 不能 大于数组的实际大小 或 小于0       
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

3、替换指定位置的元素,并返回久元素
    public E set(int index, E element) {
        rangeCheck(index);    // 指定的位置必须是有元素的位置

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

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

4、获取指定位置上的元素
    public E get(int index) {
        rangeCheck(index);    // 指定的位置必须是有元素的位置

        return elementData(index);
    }

5、删除指定位置上的元素
    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; // clear to let GC do its work

        return oldValue;
    }

6、删除某个元素
    // 遍历循环判断是否存在元素,若存在通过方法 fastRemove(int index) 删除元素
    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; // clear to let GC do its work
    }

7、获取数组中第一次出现元素的位置
    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;
    }

8、获取数组中从后往前第一次出现元素的位置
    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;
    }

9、缩减数组的容量到数组的实际大小
    // 比如创建容量大小为10的数组,添加了一个元素后,还有9各空的空间,通过trimToSize方法可以使数组的容量变为1,可以减少内存开销
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

10、清楚数组中的元素
    public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

11、删除集合中存在的所有元素
    public boolean removeAll(Collection c) {
        Objects.requireNonNull(c);    //检查集合是否是null
        return batchRemove(c, false);
    }
    
    private boolean batchRemove(Collection c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];    //如某满足条件,把元素放到数组的开头位置,指针w表示w之前的数组是符合条件的
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {    
                // 当抛出异常提前结束循环,表示r指针以后的元素是符合条件的,需要移动到指针w开始的位置
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;    //指针w之后的元素是不满足条件的元素,值为null,等待gc
                modCount += size - w;    // 计算修改次数
                size = w;
                modified = true;
            }
        }
        return modified;
    }

13、删除集合之外的所有元素
    public boolean retainAll(Collection c) {
        return batchRemove(c, true);
    }

14、添加集合中的所有元素
    public boolean addAll(Collection c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // 检查数组的容量大小,不够需要扩容
        System.arraycopy(a, 0, elementData, size, numNew);    //把数组a中从0开头的元素一共 numNew个复制到数组elementData中以size开始的位置
        size += numNew;    //计算数组elementData的大小
        return numNew != 0;
    }

15、添加集合中所有的元素到数组指定的起始位置
    public boolean addAll(int index, Collection c) {
        rangeCheckForAdd(index);    //检查指定的位置是否满足条件,0<= index <=size

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // 检查数组的容量大小,不够需要扩容

        int numMoved = size - index;    //计算数组elementData已存在的元素是否需要移动以及需要移动哪些元素,当指定的位置不是数组elementData的结尾时,需要移动
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;    //计算数组elementData的大小
        return numNew != 0;
    }

16、复制一个ArrayList实例,属性modCount =0;
    public Object clone() {
        try {
            @SuppressWarnings("unchecked")
                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();
        }
    }

17、返回一个包含list所有元素的数组对象
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

18、返回一个包含list所有元素的数组对象,具体类型
    // 如果返回数组的类型与arrayList的元素类型不符合,则会抛出异常
    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;
    }

五、可被子类继承的方法

    删除从下标fromIndex到toIndex(不包含)的元素
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

六、迭代方法

1、返回一个迭代器
    public Iterator iterator() {
        return new Itr();
    }
    
    private class Itr implements Iterator {
        int cursor;       // 指向下一个元素的指针
        int lastRet = -1; // 指向最后一次访问的元素的指针,当为-1时,表示最后一次访问的元素已经不存在
        int expectedModCount = modCount;    //表示迭代次修改list的次数,用来判断当前list是否被改动过

        public boolean hasNext() {
            return cursor != size;    // 如果下一个元素的坐标不等于list的大小,表示还有元素
        }

        @SuppressWarnings("unchecked")
        public E next() {    // 获取下一个元素
            checkForComodification();    // 检查list是否被其他方法操作
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];    // 先把下一元素的坐标 cursor 赋值改给最后一次操作元素的坐标lastRet(int i = cursor,lastRet = i),然后下一元素的坐标指向下一个坐标(cursor = i + 1),最后返回最后一次操作元素的坐标指向的元素
        }

        public void remove() {    // 删除元素
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
            // 删除元素,表示删除最后操作元素指针指向的元素, 
            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;    // 把指向下一个元素指针向前移动一位
                lastRet = -1;    // 删除元素操作只能一次,需要进行第二次需要先调用next()方法
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)    // 若迭代器里面的修改次数和list中的修改次数不同,表示在进行迭代操作时,还有list的其他操作,这是不允许的
                throw new ConcurrentModificationException();
        }
    }

2、返回ListIterator迭代器
    public ListIterator listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }

    public ListIterator listIterator() {
        return new ListItr(0);
    }
    
    private class ListItr extends Itr implements ListIterator {
        ListItr(int index) {
            super();    // 调用 Itr的构造方法,可以使用 Itr的 hasNext(),next(),remove()方法
            cursor = index;    // ListItr 继承 Itr,新增了方法previous(),set(E e),add(E e)方法
        }

        public boolean hasPrevious() {    // 判断是否有前一个元素
            return cursor != 0;
        }

        public int nextIndex() {    // 返回下一个元素的坐标
            return cursor;
        }

        public int previousIndex() {    // 返回前一个元素的坐标
            return cursor - 1;
        }

        @SuppressWarnings("unchecked")
        public E previous() {    // 获取前一个元素
            checkForComodification();
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
            // 在 lastRet 坐标修改元素,所以此方法应该在 next(),previous()方法之后调用
            try {
                ArrayList.this.set(lastRet, e);
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();
            // 在当前位置添加一个新元素,并把 cursor 指向之前的元素位置,lastRet=-1,所以 add方法之后不能调用 set(E e),remove() 方法
            try {
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

3、当使用ListIterator迭代器时,不能出现一次next()一次previous()交替使用,如:
    ArrayList list = new ArrayList<>();
		list.add("0");
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		
		ListIterator iterator = list.listIterator();
		while (iterator.hasNext()) {
			String string = (String) iterator.next();
			System.err.println(string);
			System.out.println(iterator.previous());
			
		}
    上述while()循环是死循环。

七、1.8中新增的方法

1、新增了支持函数式接口的forEach(Consumer action)方法
    方法使用:循环遍历元素
        ArrayList list = new ArrayList<>();
		list.add("0");
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		
		list.forEach((String string) -> {
		    System.out.println(string);
		});

2、支持函数式接口的removeIf(Predicate filter)方法
    方法使用:根据条件删除元素
        ArrayList list = new ArrayList<>();
		list.add("0");
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		list.forEach(string -> System.out.print(string));
		list.removeIf(string -> string.equals("2"));
		System.out.println();
		list.forEach(string -> System.out.print(string));
    结果:01234
         0134

3、支持函数式接口的replaceAll(UnaryOperator operator)方法
    方法使用:替换所有元素
        ArrayList list = new ArrayList<>();
		list.add("0");
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		list.forEach(string -> System.out.print(string + " "));
		list.replaceAll(string -> string+"replace");
		System.out.println();
		list.forEach(string -> System.out.print(string + " "));
    结果:
        0 1 2 3 4 
        0replace 1replace 2replace 3replace 4replace 

4、支持函数式接口的sort(Comparator c)方法
    方法使用:排序
        ArrayList list = new ArrayList<>();
		list.add("0");
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		list.forEach(string -> System.out.print(string + " "));
		list.sort(new Comparator() {
			@Override
			public int compare(String o1, String o2) {
				return o2.compareToIgnoreCase(o1);
			}
		});
		System.out.println();
		list.forEach(string -> System.out.print(string + " "));
    结果:
        0 1 2 3 4 
        4 3 2 1 0 

5、新增返回 Spliterator 迭代器方法
    public Spliterator spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);    // 返回的实现类是 ArrayListSpliterator
    }
    
    方法使用:
    ArrayList list = new ArrayList<>();
		list.add("0");
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		list.add("5");
		list.add("6");
		list.add("7");
		list.add("8");
		
		Spliterator spliterator = list.spliterator();
		spliterator.trySplit().forEachRemaining(string -> System.out.print(string + "  "));    // 通过trySplit()方法分割list,并返回前半部分list并遍历输入
		System.out.println();
		spliterator.forEachRemaining(string -> System.out.print(string + "  "));    //输入后半部分list
    结果:
        0  1  2  3  
        4  5  6  7  8  
    
    static final class ArrayListSpliterator implements Spliterator {
        private final ArrayList list;    //用于存放ArrayList对象
        private int index; // 起始位置(包含),advance/split操作时会修改
        private int fence; // 结束位置(不包含),-1 表示到最后一个元素
        private int expectedModCount; // 用于存放list的modCount

        // 构造方法
        ArrayListSpliterator(ArrayList list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; // OK if null unless traversed
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

        private int getFence() { // 获取结束位置
            int hi; // (a specialized variant appears in method forEach)
            ArrayList lst;
            if ((hi = fence) < 0) {
                if ((lst = list) == null)
                    hi = fence = 0;    //对fence进行赋值
                else {
                    expectedModCount = lst.modCount;    //对expectedModCount进行赋值
                    hi = fence = lst.size;    //对fence进行赋值
                }
            }
            return hi;
        }

        public ArrayListSpliterator trySplit() {    // 分割list,并返回前半部分,后半部分通过 index=mid 操作,然后父ArrayListSpliterator指向了后半部分
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null : // divide range in half unless too small
                new ArrayListSpliterator(list, lo, index = mid,
                                            expectedModCount);
        }

        public boolean tryAdvance(Consumer action) {    // 检查是否还有未处理的元素,true表示有,false表示没有
            if (action == null)
                throw new NullPointerException();
            int hi = getFence(), i = index;
            if (i < hi) {
                index = i + 1;
                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
                action.accept(e);
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

        public void forEachRemaining(Consumer action) {    // 遍历剩余的元素
            int i, hi, mc; // hoist accesses and checks from loop
            ArrayList lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if ((lst = list) != null && (a = lst.elementData) != null) {
                if ((hi = fence) < 0) {
                    mc = lst.modCount;
                    hi = lst.size;
                }
                else
                    mc = expectedModCount;
                if ((i = index) >= 0 && (index = hi) <= a.length) {
                    for (; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) a[i];
                        action.accept(e);
                    }
                    if (lst.modCount == mc)
                        return;
                }
            }
            throw new ConcurrentModificationException();
        }

        public long estimateSize() {
            return (long) (getFence() - index);
        }

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }

 

你可能感兴趣的:(java,ArrayList)