Java集合(8)——ArrayList源码解析

时间:2021-10-01 17:16:09

类图

Java集合(8)——ArrayList源码解析

官方文档

Java集合(8)——ArrayList源码解析

ArrayList成员变量

Java集合(8)——ArrayList源码解析

ArrayList构造函数

Java集合(8)——ArrayList源码解析

ArrayList内部类

Java集合(8)——ArrayList源码解析

ArrayList成员方法

Java集合(8)——ArrayList源码解析
Java集合(8)——ArrayList源码解析

ArrayList成员方法源码解析

1. public ArrayList(int initialCapacity)带参构造方法

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

源码解析:

  • 功能: 带参数构造函数,初始化数组的容量
  • 源码思路:
    • (1)判断传递进来的容量,容量值与0相比较,如果大于0,new一个Object类型的数组,将其赋给elementData
    • (2)如果容量值等于0,说明想要初始化的数组容量为空,那直接将EMPTY_ELEMENTDATA赋给elementData
    • (3)如果容量值小于0,则不符合题意,抛出异常

2. public ArrayList()空参构造方法

     public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

源码解析:

  • 功能:初始化数组元素,因为没有参数,所以默认数组的元素个数为0,将DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋给elementData

3. public ArrayList(Collection<? extends E> c)方法

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
            }
}

源码解析:

  • 功能: 初始化ArrayList元素,使用已知传递进来的元素进行初始化
  • 源码思路:
    • (1)调用Collection类型形式参数c的toArray方法,将集合元素编程数组元素,存储在elementData中
    • (2)将elementData数组的长度值赋给size,判断如果size的值不等于0,则再继续判断如果elementData数组的class值是否等于Object类型的数组的class,如果不相等,使用Arrays类的copyOf方法,给elementData数组赋初值
    • (3)如果传递进来的集合元素为null,则将elementData数组赋为初始空数组EMPTY_ELEMENTDATA

4. public void trimToSize()方法

    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

源码解析:
- 功能:修整此ArrayList实例的是列表的当前大小的容量。ArrayList所说没有用的值并不是null,而是ArrayList每次增长会申请多一点的空间,增长1.5倍+1,而不是两倍这样就会出现当size() = 1000的时候,ArrayList已经申请了1200空间的情况trimToSize 的作用只是去掉预留元素位置,就是删除多余的200,改为只申请1000,内存紧张的时候会用到
- 源码思路:
- 修改的方式是通过调用Arrays类的copyOf方法

5. public void ensureCapacity(int minCapacity)方法

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

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
}

源码解析:
- 功能: 我们在使用ArrayList时,经常要对ArrayList进行扩容
- 源码思路:
- (1)任何一个ArrayList对象都有一个capacity属性,用来指示该ArrayList的最小容量,即数组的“容纳能力”,我们知道ArrayList的内部是采用数组来存储元素的,由于Java数组是定长的,所以这个数组的大小一定是固定的,这个大小就是capacity。我们可以肯定capacity一定是大于或者等于ArrayList的size,那么当size不断增加到了要超过capacity的时候,ArrayList就不得不重新创建新的capacity来容纳更多的元素,这时需要首先建立一个更长的数组,将原来的数组中的元素赋值到新数组中,再删除原来的数组。因此当ArrayList越来越大时,这种操作的消耗也就越来越大。
- (2)为了减少这种不必要的重建capacity操作,当我们能肯定ArrayList大致有多大时,我们可以先让ArrayList把capacity设为我们期望的大小,以避免多余的数组重建
- (3)建设ArrayList自动把capacity设为10,每次重建时将长度递增原来的三分之二,那么当我们需要大约存储50个元素到ArrayList中时,就会大约需要重建数组4次,分别在增加第11、第17、第26、第39个元素的时候进行。如果我们一开始就让ArrayList的capacity为50,那么不需要任何数组重建就能完成所有插入操作了。
- (4)Java允许我们在构造ArrayList的同时指定capacity,如new ArrayList(50),也允许在以后将它设得更大,而增大capacity就是使用ensureCapacity()方法。注意:capacity只能比原来的更大,不能比原来的更小,否则Java会忽略该操作。ArrayList的初始默认capacity为10,所以给capacity指定小于10的整数毫无意义。
- (5)ArrayList的size一定小于等于capacity,而且更重要的是,访问超过size的位置将抛出异常,尽管这个位置可能没有超过capacity。ensureCapacity()只可能增加capacity,而不会对size有任何影响。要增加size,只能用add()方法

6. private static int calculateCapacity(Object[] elementData, int minCapacity)方法

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
}

源码解析:
- 功能:计算最小容量
- 源码思路:
- (1)判断如果elementData的值等于默认空数组的值,那么返回DEFAULT_CAPACITY和minCapacity中的最大值
- (2)如果elementData的值不等于默认空数组的值,则返回minCapacity值

7. private void ensureCapacityInternal(int minCapacity)方法

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

源码解析:

  • 功能:扩容入口方法

8. private void ensureExplicitCapacity(int minCapacity)方法

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

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
}

源码解析:

  • 功能:判断是否需要扩容
  • 源码思路:
    • 首先要更改modCount的值
    • 如果最小需要空间比当前的elementData的长度大,则需要扩容,调用grow扩容方法,将minCapacity传递进去

9. private void grow(int minCapacity)方法

    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

源码解析:

  • 功能:动态扩容
  • 源码思路:
    • (1)定义一个变量oldCapacity,其值等于ArrayList中elementData数组的长度
    • (2)定义一个变量newCapacity,其值等于ArrayList中elementData数组长度的1.5倍
    • (3)如果新数组的容量小于预留的数组空间,就可以直接使用这个长度新建数组
    • (4)如果新数组的容量大于预留的数组空间,就将预留数组长度设置为需要的长度
    • (5)MAX_ARRAY_SIZE 值等于Java中int的最大值。下面要判断有没有超过最大限制,如果没有,就执行下一步,如果超过最大限制,需要修改最大限制
    • (6)调用Arrays的copyOf方法将elementData数组指向新的内存空间newCapacity,并将elementData数组中的值传递到新的内存空间中

10. private static int hugeCapacity(int minCapacity) 方法

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

源码解析:

  • 功能:数组能够容纳的最大数据元素个数
  • 源码思路:
    • (1)如果数组能够容纳数据的能力小于0,说明minCapacity是错误的,因此抛出异常
    • (2)如果minCapacity的值大于数组的size,则返回整数的最大值,否则返回数组的size

11. public int size()方法

    public int size() {
        return size;
    }

源码解析:
-功能:获取数组的size大小

12. public boolean isEmpty()方法

    public boolean isEmpty() {
        return size == 0;
    }

源码解析:
- 功能:判断数组中是否有元素
- 源码思路:
- 判断size的值是否为0

13. public boolean contains(Object o)方法

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

源码解析:

  • 功能:判断一个元素是否存在在数组中
  • 源码思路:
    • 通过调用indexOf方法来实现该功能

14. public int indexOf(Object o)方法

    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,直到找到或者到数组末尾为止
  • 源码思路:
    • 分两种情况进行判断,一种是元素是null,另一种是元素非空
    • 当元素是null时,通过for循环遍历数组,当找到数组中元素==null则返回元素下标i
    • 当元素是非空时,通过for循环遍历数组,通过equals方法来判断数组中是否存在想找的元素

15. public int lastIndexOf(Object o)方法

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

源码解析:

  • 功能:从右往左判断是否有元素o,如果有则返回元素的下标,否则返回-1
  • 源码思路:
    • indexOf方法相反

16. public Object clone()方法

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

源码解析:

  • 功能:克隆
  • 源码思路:
    • (1)调用super.clone
    • (2)将elementData中的元素克隆到新的elementData中
    • (3)将新的集合的modCount 值设置为0

17. public Object[] toArray()方法

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

源码解析:

  • 功能:将集合元素变为Object类型的数组返回
  • 源码思路:
    • 实现的方式是通过Arrays类的copyOf方法实现

18. public <T> T[] toArray(T[] a)方法

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

源码解析:

  • 功能:将集合中的元素转换为泛型类型的数组,存储在参数中返回
  • 源码思路:
    • (1)如果返回的参数a的数组长度小于集合的size,说明参数不能够存储下集合中的元素,直接通过调用Arrays类的copyOf方法,将调用结果返回
    • (2)如果参数a的数组长度大于集合的size,说明参数能够存储下集合中的元素,调用System类的arraycopy方法将集合中的元素放在数组中,因为a的存储空间有多余的部分,需要最后将下标为size的元素置为null,最后返回a

19. E elementData(int index)方法

    E elementData(int index) {
        return (E) elementData[index];
    }

源码解析:

  • 功能:返回elementData数组下标为index的元素值,get方法的基础方法
  • 源码思路:
    • 因为elementData本身是数组,所以想返回下标index的元素值,直接利用数组的elementData[index]即可

20. public E get(int index)方法

    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

源码解析:

  • 功能:返回集合中下标为index的元素
  • 源码思路:
    • 首先调用rangeCheck方法判断index是否符合题意
    • 返回调用elementData方法的结果

21. public E set(int index, E element)方法

    public E set(int index, E element) {
        rangeCheck(index);

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

源码解析:

  • 功能:将集合中下标为index的元素值换为element
  • 源码思路:
    • (1)首先调用rangeCheck方法判断index下标是否符合条件
    • (2)调用elementData方法获取下标为index的元素值,将该值放在oldValue中
    • (3)将element值赋给elementData[index]中
    • (4)将旧值返回

22. public boolean add(E e)方法

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

源码解析:

  • 功能: 将元素e添加到集合中
  • 源码思路:
    • (1)首先调用ensureCapacityInternal方法,扩充数组的容量
    • (2)将将e的值添加到elementData数组中

23. public void add(int index, E element)方法

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

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

源码解析:

  • 功能:向数组下标为index的位置,插入元素element
  • 源码思路:
    • (1)首先调用rangeCheckForAdd方法,判断index是否符合条件
    • (2)调用ensureCapacityInternal方法,扩充数组的容量
    • (3)将数组中index处及其后面的值向后移动1位
    • (4)将element的值赋值给elementData数组的index下标位置
    • (5)增加size的大小

24. public E remove(int index)方法

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

源码解析:

  • 功能:将下标为index位置的元素移除
  • 源码思路:
    • (1)首先调用rangeCheck方法,用来判断index是否符合条件
    • (2)更改modCount的值
    • (3)调用elementData方法,获取index位置的元素值,放在oldValue变量中
    • (4)定义变量numMoved,其值等于size - index - 1,即将第index+1个元素及其后面的元素向前移动
    • (5)将最后一个元素赋值为null
    • (6)返回删除的元素的信息

25. public boolean remove(Object o)方法

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

源码解析:

  • 功能:从左向右一次遍历,将第一次出现的元素o从集合中删除
  • 源码思路:分两种情况进行判断,一种是o为null,另一种是o非null

26. private void fastRemove(int index)方法

    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
    }

源码解析:

  • 功能:将第index元素从集合中删除
  • 源码思路:
    • (1)首先更改modCount值,因为每从结构上修改一次集合,就要将modCount的值加1
    • (2)定义一个变量numMoved,其值等于将要移动的元素的个数
    • (3)利用System类的arraycopy方法将第index+1及其后面的元素向前移动一位,即将第index元素覆盖
    • (4)将集合最后一个元素赋为null

27. public void clear()方法

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

源码解析:

  • 功能:将集合中的元素全部删除
  • 源码思路:
    • (1)首先修改modCount的值
    • (2)利用for循环将集合中的元素全部置于null
    • (3)将size的值置为0

28. public boolean addAll(Collection<? extends E> c)方法

    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

源码解析:

  • 功能:将集合中的元素添加到现有的集合中
  • 源码思路:
    • (1)定义一个Object类型的数组a,将集合c调用toArray方法,将集合c转换为数组,放在a中
    • (2)定义一个变量numNew,用来存储数组a的长度
    • (3)调用ensureCapacityInternal方法,扩充modCount
    • (4)调用System类的arraycopy方法,将数组a中的元素copy到elementData中,数组a从下标0开始复制,复制到elementData中的下标size位置,复制numNew个元素
    • (5)最后更改size的值

29. public boolean addAll(int index, Collection<? extends E> c)方法

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

源码解析:

  • 功能:将集合中的元素添加到现有的集合中,增加一个添加的下标位置
  • 源码思路:与addAll(Collection

30. protected void removeRange(int fromIndex, int 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;
    }

源码解析:

  • 功能:将集合中的元素从下标fromIndex开始到下标toIndex移除
  • 源码思路:
    • (1)更改modCount的值,将该值自增1
    • (2)定义变量numMoved,该变量的值等于size - toIndex
    • (3)调用System类的arraycopy方法,将elementData数组中位置toIndex的值及其后面的值复制到elementData数组的fromIndex位置
    • (4)记着将newSize以后的值置为null
    • (5)更改size的值

31. private void rangeCheck(int index)方法

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

源码解析:

  • 功能: 判断index是否符合条件
  • 源码思路:
    • 如果index的值大于等于size的值,即下标的值大于数组的最大值,要抛出异常

32. private void rangeCheckForAdd(int index)方法

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

源码解析:

  • 功能:判断将要插入的元素的位置是否符合条件
  • 源码思路:
    • 插入的元素位置需要小于size大于0才符合条件,否则抛出异常

33. private String outOfBoundsMsg(int index)方法

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

源码解析:

  • 功能:抛出异常时返回的出错信息
  • 源码思路:
    • 返回元素的位置和集合的大小

34. public boolean removeAll(Collection<?> c)方法

    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

源码解析:

  • 功能:移除当前集合中集合c中所有元素
  • 源码思路:
    • (1)首先调用Objects类的requireNoNull方法,该方法用来判断c是否为null,如果为null则抛出异常,如果不为空,则返回c本身
    • (2)移除的操作是调用batchRemove方法实现

35. public boolean retainAll(Collection<?> c)方法


    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

源码解析:

  • 功能:保留当前集合中所有集合c中的元素
  • 源码思路:
    • (1)调用Objects类的requireNonNull方法,判断c是否为空
    • (2)调用batchRemove方法来实现保存操作

36. private boolean batchRemove(Collection<?> c, boolean complement)方法

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

源码解析:

  • 功能:批量删除元素,利用complement来判断是删除参数c中的元素,还是保留c中的元素。complement为true,则保留c中的元素,为false则删除c中的元素
  • 源码思路:
    • (1)定义一个Object类型的数组elementData,将当前集合的elementData值赋值给新定义的elementData
    • (2)通过for循环来修改当前集合中的元素信息,如果c中不包含elementData[r]这个元素,则直接将r位置的元素赋值给w位置的元素,w自增
    • (3)在finally中,防止抛出异常导致上面r的右移过程没完成 , 将r未右移完成的位置的元素赋值给w右边位置的元素 ,修改w值增加size-r
    • (4)如果w不等于size,说明有被覆盖掉的元素,则将w后面的元素都赋值为null ,最后修改size的值

37. public ListIterator<E> listIterator(int index)方法

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

源码解析:

  • 功能:创建ArrayList的迭代器,迭代器有起始位置
  • 源码思路:
    • (1)首先判断index值是否符合条件,如果不符合条件则抛出异常
    • (2)如果符合条件,new一个ListItr,将index值作为参数传递进去,迭代器初始位置为index

38. public ListIterator<E> listIterator()方法

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

源码解析:

  • 功能:创建ArrayList的迭代器,迭代器没有起始位置
  • 源码思路:
    • 直接返回ListItr,迭代器初始位置为0

39. public Iterator<E> iterator()方法

    public Iterator<E> iterator() {
        return new Itr();
    }

源码解析:

-功能:重写父类的iterator方法

Itr

3个成员变量

        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

1个构造方法

Itr() {}

1. public boolean hasNext()方法

        public boolean hasNext() {
            return cursor != size;
        }

源码解析:

  • 功能:判断是否还有下一个元素
  • 源码思路:
    • 通过判断当前的游标是否等于集合的size,就可以判断是否有下一个元素。

2. public E next()方法

        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;
            return (E) elementData[lastRet = i];
        }

源码解析:

  • 功能:返回当前元素的下一个元素信息
  • 源码思路:
    • (1)定义变量i,获取当前迭代器的游标位置。如果i的值大于等于size,说明迭代器已经到达了集合的最后一个位置,抛出异常
    • (2)定义Object类型的数组elementData,将当前的集合的elementData数组赋值给新的数组elementData
    • (3)如果变量i的值大于等于新定义的数组elementData的长度,抛出异常
    • (4)否则返回elementData的第i个元素,并把i的值赋值给lastRet,供下一次操作使用

3. public void remove()方法

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

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

源码解析:

  • 功能:利用迭代器删除集合中的元素
  • 源码思路:
    • (1)首先判断lastRet的值是否大于零,如果不大于零,抛出异常
    • (2)调用ArrayList类的remove方法,将下标为lastRet的值移除
    • (3)更改迭代器游标的当前位置,将其设置为lastRet
    • (4)将lastRet设置为-1
    • (5)最后要修改迭代器的expectedModCount 值,要将其与modCount保持一致,否则会触发fail-fast机制抛出异常

4. final void checkForComodification()方法

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

源码解析:

  • 功能:fail-fast机制
  • 源码思路:
    • 如果迭代器的expectedModCount值与集合的modCount不等,抛出异常

ListItr

Java集合(8)——ArrayList源码解析

1. ListItr(int index)方法

        ListItr(int index) {
            super();
            cursor = index;
        }

源码解析:

  • 功能:ListItr内部类的构造方法
  • 源码思路:将迭代器的游标置于index位置

2. public boolean hasPrevious()方法

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

源码解析:

  • 功能:判断当前元素前面是否有元素
  • 源码思路:如果迭代器的游标值不为0,说明当前元素前面有元素

3. public int nextIndex()方法

        public int nextIndex() {
            return cursor;
        }

源码解析:

  • 功能:返回元素当前位置的迭代器位置

4. public int previousIndex()方法

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

5. public E previous()方法

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

源码解析:

  • 功能:返回集合当前元素的前一个元素
  • 源码思路:
    • (1)定义一个变量i,其值等于迭代器当前游标的前一个游标值
    • (2)如果变量i的值小于0,则抛出异常,说明当前位置的前一个位置已经没有元素了
    • (3)定义一个Object类型的elementData数组,将当前集合的数组赋给刚定义的数组
    • (4)更改迭代器的游标值

6. public void set(E e)方法

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

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

源码解析:

  • 功能:利用迭代器更新元素,更改迭代器当前元素的值,其值设置为e
  • 源码思路:
    • (1)如果lastRet 的值小于0,则抛出异常
    • (2)调用ArrayList类的set方法,更改lastRet 位置的元素的值

7. public void add(E e)方法

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

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

源码解析:

  • 功能:利用迭代器向集合中添加元素e
  • 源码思路:
    • (1)定义变量i,其值等于迭代器当前的游标值
    • (2)调用ArrayList类的add方法,将e插入集合
    • (3)更改迭代器的游标值,因为增加一个元素,所以游标值+1
    • (4)设置迭代器的lastRt的值为-1
    • (5)更改迭代器的expectedModCount ,使其等于modCount的值

感谢

http://blog.csdn.net/fangchengimz/article/details/48314007