• 解释ArrayList的源码


    package java.util;
    import java.util.function.Consumer;
    import java.util.function.Predicate;
    import java.util.function.UnaryOperator;
    import sun.misc.SharedSecrets;
    实现RandomAccess这个接口的 List 集合是支持快速随机访问,for循环比迭代器快
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
        private static final long serialVersionUID = 8683452581122892189L;

    //默认初始容量为10个,也就是如果初始化数组的时候不指定ArrayList大小,

    默认为10个。

    ArrayList<String> strs = new ArrayList<String>();使用无参构造方法时并

    没有初始化数组大小,会默认大小为10,但是在初始化的时候不会设置为10个,

    会在第一次执行add操作的时候扩容为10个
        private static final int DEFAULT_CAPACITY = 10;


    //如果初始化size设置为0的话,会使用这一个数组

    private static final Object[] EMPTY_ELEMENTDATA = {};

        如果使用无参构造方法创建的ArrayList实例,会使用这一个数组。使用这个也是

    区分其他的创建实例的方式,来判断初始化数组的大小。
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    //真正存储ArrayList数据的数组,不用private修饰是为了让内部类访问简单一些
        transient Object[] elementData;
       

    //数组的大小,并不是elementData的大小,是实际存放元素的个数。
        private int size;

        //构造一个具有指定初始容量的空列表。 如果初始化容量>0,new一个初始化容量

    //的数组,赋值给elementData ,如果=0,使用共用变量,否则<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);
            }
        }

     

    //使用无参构造方法时,直接使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }

        //通过一个集合创建ArrayList,将传入集合中的元素一个个地放进数组中。
        public ArrayList(Collection<? extends E> c) {
            Object[] a = c.toArray();//该方法不传参数只能返回Object类
            if ((size = a.length) != 0) {
                if (c.getClass() == ArrayList.class) {
                    elementData = a;
                } else {
                    elementData = Arrays.copyOf(a, size, Object[].class);
                }
            } else {
                // replace with empty array.
                elementData = EMPTY_ELEMENTDATA;
            }
        }

     

    //modCount:在父类中AbstractList中定义的,初始为0,判断这个ArrayList

    //结构上被修改的次数,一般用于fast-fail模式,当这个ArrayList的迭代器

    //调用next、remove、previous、set、add方法的时候,会通过ArrayList的

    //这个字段判断数组是否发生变化,如果发生了变化,将报出异常。

     

    //这个方法的作用是将ArrayList中存放元素的Array的大小调整为实际元素

    //的个数。减少ArrayList实例的存储空间,如果大小为0的话,赋值为

    //EMPTY_ELEMENTDATA

    public void trimToSize() {
            modCount++;
            if (size < elementData.length) {
                elementData = (size == 0)
                  ? EMPTY_ELEMENTDATA
                  : Arrays.copyOf(elementData, size);
            }
        }
     
        //array的最大能扩容到的长度     

    //有些VM在array中需要一个头部的数据,所以要-8
        //如果大小超过这个大小,可能出现内存溢出的异常

    //如果你的数组大小不能设置成这么大,可能是VM配置或硬件问题(这个没有研究过)

    //https://blog.csdn.net/weixin_30810583/article/details/96248144(看看这个)

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    //大容量扩容,这个函数只能是尽量给你扩容,但是能不能扩还要看VM支持不支持,

    //详见上面的MAX_ARRAY_SIZE解释

    private static int hugeCapacity(int minCapacity) {

    //如果数值太大导致内存溢出,出现负数的情况,直接抛出异常
            if (minCapacity < 0)

           throw new OutOfMemoryError();

    //如果数值大于MAX_ARRAY_SIZE,只能赌一下你的VM不会在array中添加一个头部的数据
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }

    //扩容以确保它至少可以容纳参数指定的元素数。

    //这块代码可能出现溢出的情况
        private void grow(int minCapacity) {
            int oldCapacity = elementData.length;

    //java策略产生的扩容数量,即1.5*原来的的容量,右移为*0.5
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            //如果java默认策略的扩容数量无法达到参数指定的最小容量,那么放弃默认策略,

    //按照参数指定的容量进行扩容,如果默认策略大,就按照策略的。

    if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;

    //判断扩容后的容量是否>数组的最大容量,可能出现风险,要用参数的试一下,因为

    //对于本次扩容扩容来说,参数值肯定是最小的,试试这个最小值(newCapacity可能

    //因为比参数大,导致用的是策略的值)。

      if (newCapacity - MAX_ARRAY_SIZE > 0)

    //执行大容量扩容的函数,这个函数可能会出现异常
                newCapacity = hugeCapacity(minCapacity);

    //将原来的数组复制到一个新的数组中(新数组的长度是扩容后的长度)
            elementData = Arrays.copyOf(elementData, newCapacity);
        }

        //作用就是根据传过来的容量,判断是不是需要扩容,只有需要的容量大于当前容量,才要扩容

    private void ensureExplicitCapacity(int minCapacity) {

     //这个modCount++执行了,但是如果需要的容量<=当前容量的时候,ArrayList的结构是

    //不会发生变化的,也就是说modCount变化并不代表真的变了。Iterator抛出异常并不代表

    //ArrayList变了
            modCount++;
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }

        

    //根据参数去扩大ArrayList的容量
        public void ensureCapacity(int minCapacity) { 

    //判断是不是通过无参构造方法创建的ArrayList实例(只有用无参构造方法才会是这个)

    //如果是的话,他的默认大小已经是10了,所以不能比他小

    ///如果不是,可以是任意数,因为如果是其他的方法创建的实例,大小可能是>0的任意数
            int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)

                ? 0
                : DEFAULT_CAPACITY;
            //只有符合最小值才能去扩展
            if (minCapacity > minExpand) {
                ensureExplicitCapacity(minCapacity);
            }
        }
     

    //这个方法和上面的方法的区别是:

    //ensureCapacity:如果传入的minCapacity不符合最小的值,就不会进一步给你扩容了,可能是你

    //数字输入错误,但是方法方法不知不觉的不给你执行下面的扩容

    //ensureCapacityInternal:如果传入的minCapacity不符合扩容最小值,会计算出一个合适的值去

    执行下面的扩容过程

        private void ensureCapacityInternal(int minCapacity) {
            ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
        }

    //通过传入的最小参数,给出一个适合的扩展值。和ensureCapacityInternal配合使用
        private static int calculateCapacity(Object[] elementData, int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            return minCapacity;
        }

     
       
        //返回ArrayList的元素数量(不是总容量)

    public int size() {
            return size;
        }

        //判断ArrayList中是否有元素
        public boolean isEmpty() {
            return size == 0;
        }

     

    //如果参数在ArrayList中存在(equals(包括null)),则返回true,否则,返回false,详见indexOf函数
        public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }

       //查询出该元素在ArrayList中第一次出现的位置,如果不存在则返回-1,通过equals进行判断
        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;
        }

        

    //查询出该元素在ArrayList中最后一次出现的位置,如果不存在则返回-1,通过equals进行判断

    //这个可以记一下,第一次出现的位置从第一个开始遍历,最后一次出现的位置从最后一个开始遍历

    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;
        }

    //ArrayList的一个浅克隆

    //深克隆(虽然说v.elementData对象变化了,但是这个elementData数组中的引用却由于copyOf是

    一个浅拷贝,elementData中元素的对象引用没有发生变化,当这个elementData中的元素发生变化

    时,被克隆和克隆的对象都会变化。所以这个是一个浅拷贝被克隆的对象和克隆的对象内部出现一个

    相同的引用,都不叫深克隆)

      public Object clone() {
            try {
                ArrayList<?> v = (ArrayList<?>) super.clone();

    //把里面的元素拷贝一份
                v.elementData = Arrays.copyOf(elementData, size);
                v.modCount = 0;
                return v;
            } catch (CloneNotSupportedException e) {
                    throw new InternalError(e);
            }
        }

       //ArrayList转化成Array
        public Object[] toArray() {
            return Arrays.copyOf(elementData, size);
        }

        //将ArrayList中的内容放到传进来的数组中

    //如果传进来的数组小于ArrayList的大小,直接重新建一个数组传出去

    //否则将ArrayList中的元素拷贝进传进来的数组中

    //如果传进来的数组大于ArrayList的大小,在index=size的位置置为null,

    //用来判断结尾。在程序中设置为null是为了放置传进来的数组里面有内容。
        @SuppressWarnings("unchecked")
        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;
        }
        

    //访问ArrayList中固定位置的元素
        @SuppressWarnings("unchecked")
        E elementData(int index) {
            return (E) elementData[index];
        }


        //检测传进来的下标是否合理(0~size),很多方法用到,所以单独出来的方法,不去判断<0

    //让数组自己报错。
        private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

     

    //访问ArrayList中固定位置的元素,多了一个rangeCheck,外面直接调用这个就行

    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;
        }

        //在ArrayList中的array最后添加元素
        public boolean add(E e) {

    //调用这个方法会使modCount+1
            ensureCapacityInternal(size + 1);

    //size+1并设值,这个写法很不错

    //element[size] = e ;size ++ => elementData[size++] = e;

      elementData[size++] = e;
            return true;
        }

        //在指定位置添加元素,并将该位置和该位置后面的元素后移

    public void add(int index, E element) {
            rangeCheckForAdd(index);

    //每次添加元素前都要看看是不是要扩容
            ensureCapacityInternal(size + 1);  

    //arraycopy不仅仅用于两个数组,可以一个数组之间复制

    System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }

    //删除指定位置的元素,并且将该元素后面的往前移动,返回删除的元素
          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 ; size--
            elementData[--size] = null;
            return oldValue;
        }

        //删除ArrayList中的指定元素(第一个出现的),并返回删除结果
        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
            modCount++;
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            elementData[--size] = null;

     }

       //将ArrayList中的元素置为null,并且将size变成0
        public void clear() {
            modCount++;

    for (int i = 0; i < size; i++)
                elementData[i] = null;

            size = 0;
        }

       //将一个集合中的元素加入到ArrayList的array中
        public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
            return numNew != 0;
        }

        //将集合中的元素插入到ArrayList中,插入位置和插入位置后的元素移动集合的长度个单位,返回

    添加的结果

    public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);

            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount

            int numMoved = size - index;
            if (numMoved > 0)
                System.arraycopy(elementData, index, elementData, index + numNew,numMoved);

            System.arraycopy(a, 0, elementData, index, numNew);
            size += numNew;
            return numNew != 0;
        }
        //将ArrayList下标范围内的元素删除
           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;
        }

     
        //添加元素时做的范围检查,这个必须要判断是否小于0,因为添加的时候会有下面的操作

    //扩容或者调整元素,如果在调整过程中发现越界,前面的操作无法撤回。Index为什么要

    //小于等于size:System.arraycopy(elementData, index, elementData, index + 1,
        //size - index);如果index>size,最后一个参数<0,这个函数会报错,但是=0可以不移动
        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;
        }

        //将ArrayList中包含的c集合的元素删除掉,需要判断c不为null.
        public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, false);
        }

        //和removeAll相反,这个方法留下的是和c集合的元素相同的元素.
        public boolean retainAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, true);
        }

    //批量删除ArrayList中的元素,通过complement来判断是否保留/删除c的元素。

    private boolean batchRemove(Collection<?> c, boolean complement) {
            final Object[] elementData = this.elementData;
            int r = 0, w = 0;

    //设置更改状态为false
            boolean modified = false;
            try {
                for (; r < size; r++)

    //遍历整个array,将需要保留的数据放在前面
                    if (c.contains(elementData[r]) == complement)
                        elementData[w++] = elementData[r];
            } finally {

    //这个注释也不知道是什么意思
                // Preserve behavioral compatibility with AbstractCollection,
                // even if c.contains() throws.  

    //如果发生异常导致未遍历完成,那么将未遍历的元素放在后面,当成是需要保留的数据
                if (r != size) {
                    System.arraycopy(elementData, r,elementData, w,size - r);

    //保留的数据个数需要添加上后面没有遍历的数据个数
                    w += size - r;
                }
                //将保留的数据后面的位置置为空,并且更改size为保留的数据的个数

    if (w != size) {
                    // clear to let GC do its work
                    for (int i = w; i < size; i++)
                        elementData[i] = null;
                    modCount += size - w;
                    size = w;
                    modified = true;
                }
            }
            return modified;
        }

     
        //将ArrayList序列化到文件中。用ObjectOutputStream的writeObject方法时会调用这

    个方法去写入磁盘

    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException{   
         // Write out element count, and any hidden stuff
            int expectedModCount = modCount;
            s.defaultWriteObject();

            // Write out size as capacity for behavioural compatibility with clone()
            s.writeInt(size);

            // Write out all elements in the proper order.
            for (int i=0; i<size; i++) {
                s.writeObject(elementData[i]);
            }

            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }

     

     

     

     

     


        //通过文件流反序列化成ArrayList对象
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            elementData = EMPTY_ELEMENTDATA;
            s.defaultReadObject();
            s.readInt(); // ignored
            if (size > 0) {
                int capacity = calculateCapacity(elementData, size);
                SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
                ensureCapacityInternal(size);

                Object[] a = elementData;
                // Read in all elements in the proper order.
                for (int i=0; i<size; i++) {
                    a[i] = s.readObject();
                }
            }
        }


        //ArrayList内部自己定义的Iterator
        private class Itr implements Iterator<E> {
            int cursor;       //下一个返回元素的索引

        int lastRet = -1; //当前遍历到的位置的索引

    int expectedModCount = modCount;记录创建迭代器的modCount

            Itr() {} //无参构造方法
           //判断是否遍历完成,后面是否有元素

    public boolean hasNext() {
                return cursor != size;
            }
            //判断在迭代器(Itr)创建之后ArrayList是否发生变化,如果发生变化,直接抛出异常
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }

    //获取cursor处的元素(即下一个元素,因为cursor指的是当前遍历的下一个位置)
            @SuppressWarnings("unchecked")
            public E next() {
                checkForComodification();

    //共享的变量都不可靠
                int i = cursor;

    if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();

    //游标往后移动一位,下一个位置
                cursor = i + 1;

    //返回当前遍历到的元素,并且修改当前位置LastRet,因为下一个已经取出来了,所以当前

    //位置应该修改
                return (E) elementData[lastRet = i];
            }
            删除当前遍历到的元素(只能删除最后一次遍历到的元素,如果这个元素被删除,lastRet需

    要变成-1,如果不变的话,下一次调用删除这时候删除的就不是最后一次遍历到的元素了,删

    除不能乱删除,如果说lastRet不变的话,这个删除函数就没有道理了,我函数没有指定哪个下

    标的元素,就给我删除了,这不是乱删除吗,如果我置成-1,这个函数的原理就是删除最后一次

    遍历到的元素,在删除一次后下一次就不能删除了。因为当前遍历到的元素已经没了。所以置成

    -1)
            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {

    //调用ArrayList自己的方法去删除ArrayList的元素
                    ArrayList.this.remove(lastRet);

    //cursor移动到当前位置,因为是删除了一个,所以下一次遍历应该是当前位置
                    cursor = lastRet;

    //lastRet修改为-1

    lastRet = -1;

    //同步modCount的值
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

     

    //对剩余的元素进行操作(从cursor开始到最后),consumer.accept是对剩余元素的操作)

    //Consumer是函数式接口.
            @Override
            @SuppressWarnings("unchecked")
            public void forEachRemaining(Consumer<? super E> 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();
                }

    //当没有遍历到最后一个元素且ArrayList没有被其他程序修改的时候。
                while (i != size && modCount == expectedModCount) {
                    consumer.accept((E) elementData[i++]);
                }
                

                //重新修改cursor的值,如果这样的话,其实这个函数针对的是最后面的几个操作相同,前面的操作不同的情况,最后这几个直接一次遍历完

    cursor = i;

    //修改lastRet
                lastRet = i - 1;
                checkForComodification();
            }

     

    //ArrayList自己定义的一个ListIterator
            private class ListItr extends Itr implements ListIterator<E> {

    //传入起始位置,从该位置开始遍历
            ListItr(int index) {
                super();
                cursor = index;
            }
            //判断当前位置前面是否有元素
            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) {

    //lastRet<0说明当前元素已经删除或者迭代器还没有遍历,所以说没有当前遍历到的元素
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();

                try {

    //调用ArrayList自己的方法去修改ArrayList的元素
                    ArrayList.this.set(lastRet, e);
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }

    //在当前遍历到的位置添加一个元素
            public void add(E e) {
                checkForComodification();
                try {
                    int i = cursor;

    //调用ArrayList自己的方法在当前位置去添加元素                

    ArrayList.this.add(i, e);
                    cursor = i + 1;

    //因为当前位置已经不是遍历到的元素了,所以置为-1

    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
        }

      

     //创建一个ListItr,从ArrayList的指定位置开始

    public ListIterator<E> listIterator(int index) {
            if (index < 0 || index > size)
                throw new IndexOutOfBoundsException("Index: "+index);
            return new ListItr(index);
        }

        //创建一个ListItr,从ArrayList的第一个位置开始

    public ListIterator<E> listIterator() {
            return new ListItr(0);
        }

    //创建一个Itr,从ArrayList的第一个位置开始
        public Iterator<E> iterator() {
            return new Itr();
        }

        //使用自己的内部类截取ArrayList本身的一部分
        public List<E> subList(int fromIndex, int toIndex) {

    //截取之前对截取的位置做一下判断
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
        //对截取的位置进行判断
        static void subListRangeCheck(int fromIndex, int toIndex, int size) {
            if (fromIndex < 0)
                throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
            if (toIndex > size)
                throw new IndexOutOfBoundsException("toIndex = " + toIndex);
            if (fromIndex > toIndex)
                throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                                   ") > toIndex(" + toIndex + ")");
        }
        

        //截取ArrayList中的一部分。需要注意的是,这个内部类只能被外部类调用

        //因为这个内部类由private修饰,无法使用Out.In in = new Out().new In()

        //这种方式被其他的类访问,而外部类中调用内部类的方法为subList方法,它

        //调用这个类的构造方法时,传进来的参数是ArrayList本身。所以这个内部类

        //主要的作用就是截取外部类实例的一部分,并不能截取其他的对象。然后其实

        //这个类的操作是和ArrayList相似的,且大多调用的是ArrayList本身的方法,

        //唯一不一样的是起始位置不同,所以subList中的方法和ArrayList本身的操作

        //就是多了一个偏移量。这部分将粗略说明,如果不懂,可以看ArrayList的同名

    //方法。还有就是subList中的所有操作都是针对外部类对象ArrayList中的内容

    //进行修改的

        private class SubList extends AbstractList<E> implements RandomAccess {

    //原来的集合,其实就是外部类的实例
            private final AbstractList<E> parent;
            private final int parentOffset;

    private final int offset;
            int size;
            SubList(AbstractList<E> parent,int , int fromIndex, int toIndex) {
                this.parent = parent; //外部类实例本身
                this.parentOffset = fromIndex;  //截取开始位置
                this.offset = offset + fromIndex; //offset是0,所以offset = parentOffset
                this.size = toIndex - fromIndex; //截取的长度
                this.modCount = ArrayList.this.modCount;//因为截取的是外部类实例本身,所以用外部

    类的modCount
            }
            

        //判断该位置是否超出了subList的边界

    private void rangeCheck(int index) {
                 if (index < 0 || index >= this.size)
                     throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }

        

        //判断外部的modCount是否发生变化,也就是他的结构是否发生变化

        private void checkForComodification() {
                if (ArrayList.this.modCount != this.modCount)
                    throw new ConcurrentModificationException();
             }

    //修改index处的值,注意一点:这个subList的策略是:当执行set、get操作时

    //考虑了偏移量(offset),其他的情况并没有计算偏移量。也就是说外面

    //传递进来的offset是用于获取某个index处的值或者设置某一个index处的值时用的。

    //,如果是截取的subList的外部类对象,其实是没有问题的,因为外部类调用时offset

    //设置的是0,对于结果上来说没有影响。但是我不是很清楚这样设计的用意,就不解释了。

    //如果某一天其他的对象调用到了这个私有内部类(应该不太可能),就需要注意了,设置

    //获取的时候使用了偏移量,其他情况没有使用偏移量。看看subList的方法是否会对结果

    //有影响。

    public E set(int index, E e) {
                rangeCheck(index);
                checkForComodification();

    //使用ArrayList.set相同的做法,不同的是index是加了offset

    //下面很多都是这样的
                E oldValue = ArrayList.this.elementData(offset + index);
                ArrayList.this.elementData[offset + index] = e;
                return oldValue;
           }


            //获取index处的值
            public E get(int index) {
                rangeCheck(index);
                checkForComodification();

    //这里也是计算了偏移量
                return ArrayList.this.elementData(offset + index);
            }

    //返回subList的长度,也就是截取的长度
            public int size() {
                checkForComodification();
                return this.size;
            }
            

    //在index处添加一个元素,添加元素时没有考虑offset偏移量的问题

    public void add(int index, E e) {
                rangeCheckForAdd(index);
                checkForComodification();

    //调用父类的add方法,是从截取的初始位置开始计算的。

    //很正常的操作
                parent.add(parentOffset + index, e);

    //外部类对象结构变化了,需要重新获取modCount
                this.modCount = parent.modCount;

    //虽然针对外部类进行操作,且fromIndex和toIndex没有变化,但是size还是要++,

    //刚开始的fromIndex和toIndex是为了第一次初始化的,以后就没什么用了,因为

    //对subList执行了add操作,所以从逻辑上讲subList的长度是要+1的

                this.size++;
            }
            //删除某一个位置的数据
            public E remove(int index) {
                rangeCheck(index);
                checkForComodification();
                E result = parent.remove(parentOffset + index);
                this.modCount = parent.modCount;
                this.size--;
                return result;
            }
            //删除一个范围内的数据
            protected void removeRange(int fromIndex, int toIndex) {
                checkForComodification();
                parent.removeRange(parentOffset + fromIndex,
                                   parentOffset + toIndex);
                this.modCount = parent.modCount;
                this.size -= toIndex - fromIndex;
            }

    //将c中的元素全部添加到subList的末尾
            public boolean addAll(Collection<? exends E> c) {
                return addAll(this.size, c);
            }
            //在index位置把c中的元素全部添加
            public boolean addAll(int index, Collection<? extends E> c) {
                rangeCheckForAdd(index);
                int cSize = c.size();
                if (cSize==0)
                    return false;

                checkForComodification();
                parent.addAll(parentOffset + index, c);
                this.modCount = parent.modCount;
                this.size += cSize;
                return true;
            }
            //将subList生成一个迭代器,调用的是父类AbstractList中的方法,从subList的第

    //0位开始遍历

    public Iterator<E> iterator() {
                return listIterator();
            }
             //将subList生成一个迭代器,调用的是父类AbstractList中的方法,从subList的第

    //index位开始遍历
            public ListIterator<E> listIterator(final int index) {
                checkForComodification();
                rangeCheckForAdd(index);
                final int offset = this.offset;
                //一个匿名内部类,实现了ListIterator接口,操作和ArrayList的迭代器操作差不多
                return new ListIterator<E>() {
                    int cursor = index;
                    int lastRet = -1;
                    int expectedModCount = ArrayList.this.modCount;
                    
                    public boolean hasNext() {
                        return cursor != SubList.this.size;
                    }
                    //subList的迭代器的原则和sublist的原则一样,设置、获取元素时,考虑偏移

    //添加删除不考虑偏移
                    @SuppressWarnings("unchecked")
                    public E next() {
                        checkForComodification();
                        int i = cursor;
                        if (i >= SubList.this.size)
                            throw new NoSuchElementException();
                        Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();
                        cursor = i + 1;
                        return (E) elementData[offset + (lastRet = i)];
                    }

                    public boolean hasPrevious() {
                        return cursor != 0;
                    }

                    @SuppressWarnings("unchecked")
                    public E previous() {
                        checkForComodification();
                        int i = cursor - 1;
                        if (i < 0)
                            throw new NoSuchElementException();
                        Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();
                        cursor = i;
                        return (E) elementData[offset + (lastRet = i)];
                    }

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

                    public int nextIndex() {
                        return cursor;
                    }

                    public int previousIndex() {
                        return cursor - 1;
                    }

                    public void remove() {
                        if (lastRet < 0)
                            throw new IllegalStateException();
                        checkForComodification();

                        try {
                            SubList.this.remove(lastRet);
                            cursor = lastRet;
                            lastRet = -1;
                            expectedModCount = ArrayList.this.modCount;
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }

                    public void set(E e) {
                        if (lastRet < 0)
                            throw new IllegalStateException();
                        checkForComodification();

                        try {
                            ArrayList.this.set(offset + lastRet, e);
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }

                    public void add(E e) {
                        checkForComodification();

                        try {
                            int i = cursor;
                            SubList.this.add(i, e);
                            cursor = i + 1;
                            lastRet = -1;
                            expectedModCount = ArrayList.this.modCount;
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }

                    final void checkForComodification() {
                        if (expectedModCount != ArrayList.this.modCount)
                            throw new ConcurrentModificationException();
                    }
                };
            }
            //subList还可以再次截取,变成另外一个subList,但是操作的还是外部类对象
            public List<E> subList(int fromIndex, int toIndex) {
                subListRangeCheck(fromIndex, toIndex, size);
                return new SubList(this, offset, fromIndex, toIndex);
            }
            

    //判断index是否超出sublist的范围
            private void rangeCheck(int index) {
                 if (index < 0 || index >= this.size)
                     throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
           }


            private void rangeCheckForAdd(int index) {
                if (index < 0 || index > this.size)
                    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }

            private String outOfBoundsMsg(int index) {
                return "Index: "+index+", Size: "+this.size;
            }

            //将subList转换成ArrayListSpliterator,其中开始位置设置为offset,结束位置为offset

    +subList的大小
            public Spliterator<E> spliterator() {
                checkForComodification();
                return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                                   offset + this.size, this.modCount);
            }
        }
        //将ArrayListlist中的元素做同一个操作,就是相当于for循环,传递的Consumer函数接口就是对

    //ArrayList中所有元素的操作
        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            final int expectedModCount = modCount;
            @SuppressWarnings("unchecked")
            final E[] elementData = (E[]) this.elementData;
            final int size = this.size;
            for (int i=0; modCount == expectedModCount && i < size; i++) {
                action.accept(elementData[i]);
            }
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }

    //将ArrayList生成一个spliterator
       @Override
        public Spliterator<E> spliterator() {
            return new ArrayListSpliterator<>(this, 0, -1, 0);
        }

        //实现util包中的Spliterator接口(可以被切割的迭代器)
        static final class ArrayListSpliterator<E> implements Spliterator<E> {

    private final ArrayList<E> list;
    private int index;
    private int fence;

    private int expectedModCount;


            ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                                 int expectedModCount) {
                this.list = list;  //被迭代的ArrayList本身

      this.index = origin; //起始位置orgin翻译过来也是有原点起源的意思
                this.fence = fence; //最终位置
                this.expectedModCount = expectedModCount;
            }

            private int getFence() {
                int hi; // (a specialized variant appears in method forEach)
                ArrayList<E> lst;

    //第一次调用getFence()的时候,因为ArrayList传进来为-1,相当于初始化fence
                if ((hi = fence) < 0) {

         //如果传进来的list是null,设置fence设置为0
                    if ((lst = list) == null)
                        hi = fence = 0;

         //否则设置ArrayList的size,所以fence记录的是ArrayList的大小,并且初始化

    //expectedModCount为list的modcount,方便查看ArrayList是否发生结构性变化
                    else {
                        expectedModCount = lst.modCount;
                        hi = fence = lst.size;
                    }
                }

    //返回ArrayList的大小
                return hi;
            }
            //将这个ArrayListSpliterator拆分为两个ArrayListSpliterator
            public ArrayListSpliterator<E> trySplit() {

    //得到中间的位置右移一位相当于是/2
                int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;

    //如果初始位置>=最后的位置,说明已经不能再去分割了
                return (lo >= mid) ? null : // divide range in half unless too small

    //如果能够分割,将右边的一半赋值给新的ArrayListSpliterator,并未进行真正的

    //只是将两个ArrayListSpliterator的可操作性区域进行了设定
                    new ArrayListSpliterator<E>(list, lo, index = mid,
                                                expectedModCount);
            }
            //获取遍历到的元素,并按照传进来的实现的接口的方法进行操作
            public boolean tryAdvance(Consumer<? super E> action) {
                if (action == null)
                    throw new NullPointerException();
                int hi = getFence(), i = index;

    //判断index是否超过ArrayListSpliterator的最大范围
                if (i < hi) {

    //将index移动到下一个

    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;
            }
            //操作剩余的元素,即index到fence处的元素
            public void forEachRemaining(Consumer<? super E> action) {
                int i, hi, mc; // hoist accesses and checks from loop
                ArrayList<E> 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);
            }
            //返回该Spliterator的特性
            public int characteristics() {
                return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
            }
        }

    //根据传进来的Predicate函数式接口,来判断元素是否要被删除,根据他来删除元素
        @Override
        public boolean removeIf(Predicate<? super E> filter) {

    //每次都是先判断传递进来的是不是非空
            Objects.requireNonNull(filter);

    //初始化要删除的元素个数为0
            int removeCount = 0;

    //创建一个bitSet来记录要删除的元素的下标
            final BitSet removeSet = new BitSet(size);
            final int expectedModCount = modCount;
            final int size = this.size;
            for (int i=0; modCount == expectedModCount && i < size; i++) {
                @SuppressWarnings("unchecked")
                final E element = (E) elementData[i];
                if (filter.test(element)) {

    //如果该元素需要被删除,将这个位置记录下来
                    removeSet.set(i);
                    removeCount++;
                }
            }
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            //通过要删除元素的个数是否>0来判断是否执行删除
            final boolean anyToRemove = removeCount > 0;
            if (anyToRemove) {
                final int newSize = size - removeCount;
                for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {

    //得到i的下一个不应该被删除的位置(包括i本身)
                    i = removeSet.nextClearBit(i);
                    elementData[j] = elementData[i];
                }

    //将后面的元素补充null
                for (int k=newSize; k < size; k++) {
                    elementData[k] = null;  // Let gc do its work
                }
                this.size = newSize;
                if (modCount != expectedModCount) {
                    throw new ConcurrentModificationException();
                }
                modCount++;
            }

            return anyToRemove;
        }

     

    //将list中的元素按照传进去的函数转换成另一个元素

     @Override
        @SuppressWarnings("unchecked")
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            final int expectedModCount = modCount;
            final int size = this.size;
            for (int i=0; modCount == expectedModCount && i < size; i++) {
                elementData[i] = operator.apply((E) elementData[i]);
            }
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

    //调用Arrays里面的方法去对内部数组排序
        @Override
        @SuppressWarnings("unchecked")
        public void sort(Comparator<? super E> c) {
            final int expectedModCount = modCount;
            Arrays.sort((E[]) elementData, 0, size, c);
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
    }

  • 相关阅读:
    docker生态系统
    访问远程的docker
    docker实践4
    docker实践3
    docker实践
    Spark快速入门
    shuffle和sort分析
    hadoop原理
    apacheds的客户端
    LDAP apacheds解决方案
  • 原文地址:https://www.cnblogs.com/heibo/p/15154793.html
Copyright © 2020-2023  润新知