• Java基础-集合框架-ArrayList源码分析


    一、JDK中ArrayList是如何实现的

    1、先看下ArrayList从上而下的层次图:

     说明:

      从图中可以看出,ArrayList只是最下层的实现类,集合的规则和扩展都是AbstractList、List、Collection等上层的接口所设定的,而ArrayList实现或继承了上层的规则,然后重新或扩展来处理集合中的数据。

    2、看看接口:Iterable<E>中都定义了那些规则?

    JDK1.8中的源码:

     1 package java.lang;
     2 
     3 import java.util.Iterator;
     4 import java.util.Objects;
     5 import java.util.Spliterator;
     6 import java.util.Spliterators;
     7 import java.util.function.Consumer;
     8 public interface Iterable<T> {//实现这个接口允许对象成为 "foreach" 语句的目标。 
     9     Iterator<T> iterator();
    10     default void forEach(Consumer<? super T> action) {
    11         Objects.requireNonNull(action);
    12         for (T t : this) {
    13             action.accept(t);
    14         }
    15     }
    16     default Spliterator<T> spliterator() {
    17         return Spliterators.spliteratorUnknownSize(iterator(), 0);
    18     }
    19 }

     这里说明一下:

    (1)Consumer<? super T> action  可以理解为:实现了Consumer接口的实现类对象。
    (2)accept(T t) T 是每一次forEach方法处理的数据类型,t是数据
    (3)
    spliterator():Spliterator(splitable iterator可分割迭代器)接口是Java为了并行遍历数据源中的元素而设计的迭代器。也就是收JDK1.8版本已经支持多核并发处理集合中的数据了,你只需要告诉JDK你要做什么并行任务,关注业务本身,至于如何并行,怎么并行效率最高,就交给JDK自己去思考和优化速度了。

    简单举个forEach的例子:

     1 package com.xfwl.test;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 import java.util.function.Consumer;
     6 @SuppressWarnings("unchecked")
     7 public class Test2 {
     8     public static void main(String[] args) {
     9         List alist=new ArrayList();
    10         alist.add("1");
    11         alist.forEach(new T());
    12     }
    13     /**
    14      * Consumer接口测试实现类T
    15      * @param <E>
    16      */
    17     static  class T implements Consumer{
    18         public T(){}
    19         public void accept(Object e) {
    20             System.out.println("当前数据:"+e);
    21         }
    22         public Consumer andThen(Consumer after) {
    23             // TODO Auto-generated method stub
    24             return null;
    25         }
    26     }
    27 }

     运行结果:

    当前数据:1

    总结一下:

      (1)接口Iterable,定义了遍历集合中的数据的方法:forEach(),这个方法需要一个实现了Consumer接口的参数;

       (2)接口Iterable,定义了一个可以实现并发的迭代器,具体如何实现和优化交给jdk自己处理,我们只负责使用集合即可。

    3、看看接口:Collection<E>中定义了那些规则?

    JDK1.8中的源码: 

     1 package java.util;
     2 import java.util.function.Predicate;
     3 import java.util.stream.Stream;
     4 import java.util.stream.StreamSupport;
     5 
     6 public interface Collection<E> extends Iterable<E> {
     7     int size();                                    //获取集合元素总数
     8     boolean isEmpty();                            //判断集合是否非空
     9     boolean contains(Object o);                    //判断集合是否包含指定元素
    10     Iterator<E> iterator();                        //获取迭代器
    11     Object[] toArray();                            //把集合转化成Object类型数组对象
    12     <T> T[] toArray(T[] a);                        //把集合转化成指定T类型数组对象
    13     boolean add(E e);                            //添加数据到集合
    14     boolean remove(Object o);                    //从集合中移除数据
    15     boolean containsAll(Collection<?> c);        //集合是否包含另一个集合
    16     boolean addAll(Collection<? extends E> c);    //集合添加另外一个集合
    17     boolean removeAll(Collection<?> c);            //集合中移除另外一个集合中的内容
    18     default boolean removeIf(Predicate<? super E> filter) {//JDK1.8开始加入的方法,按指定条件移除集合中的信息
    19         Objects.requireNonNull(filter);
    20         boolean removed = false;
    21         final Iterator<E> each = iterator();
    22         while (each.hasNext()) {
    23             if (filter.test(each.next())) {
    24                 each.remove();
    25                 removed = true;
    26             }
    27         }
    28         return removed;
    29     }
    30     boolean retainAll(Collection<?> c);            //移除此 collection 中未包含在指定 collection 中的所有元素
    31     void clear();                                //清除集合中的信息
    32     boolean equals(Object o);                    //比较此 collection 与指定对象是否相等。
    33     int hashCode();                                //返回此 collection 的哈希码值。
    34     @Override
    35     default Spliterator<E> spliterator() {        //JDK1.8开始新加入的方法,返回当前集合的并发迭代器
    36         return Spliterators.spliterator(this, 0);
    37     }
    38     default Stream<E> stream() {                //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据
    39         return StreamSupport.stream(spliterator(), false);//返回的流是顺序的
    40     }
    41     default Stream<E> parallelStream() {        //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据
    42         return StreamSupport.stream(spliterator(), true);//返回的流是并行的
    43     }
    44 }

     这里说明一下:

    (1)JDK8版本中,接口中可以定义方法的实现了,即方法可以定义方法体了。

    (2)Collection中定义了一些针对集合数据的添加,删除,判空,是否存在,整块集合的包含+移除等操作,以及JDK1.8开始新增的方法:removeIf()和spliterator(),stream()以及parallelStream()方法。

    简单举个stream()的例子:

     1 package com.xfwl.test;
     2 
     3 import java.util.Arrays;
     4 import java.util.List;
     5 import java.util.function.Consumer;
     6 import java.util.stream.Collectors;
     7 @SuppressWarnings("unchecked")
     8 public class Test2 {
     9     public static void main(String[] args) {
    10         List<Integer> alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    11         alist=alist.stream().filter(s -> (s>5)).collect(Collectors.toList());//lumbda表达式

    12 for(int i:alist){ 13 System.out.println(i); 14 } 15 16 } 17 }

     运行结果:

    6
    7
    8
    9
    10

    继续修改代码,举个removeIf()的例子:

     1 package com.xfwl.test;
     2 
     3 import java.util.Arrays;
     4 import java.util.List;
     5 import java.util.function.Consumer;
     6 import java.util.stream.Collectors;
     7 @SuppressWarnings("unchecked")
     8 public class Test2 {
     9     public static void main(String[] args) {
    10         List<Integer> alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    11         alist=alist.stream().filter(s -> (s>5)).collect(Collectors.toList());//lumbda表达式
    12         alist.removeIf(s->s==10);
    13         for(int i:alist){
    14             System.out.println(i);
    15         }
    16     }
    17 }

     运行结果:

    6
    7
    8
    9

    4、看看抽象类:AbstractCollection<E>中定义了那些规则?

    JDK1.8中的源码 

      1 package java.util;
      2 public abstract class AbstractCollection<E> implements Collection<E> {
      3     protected AbstractCollection() {
      4     }
      5     public abstract Iterator<E> iterator();
      6 
      7     public abstract int size();
      8 
      9     public boolean isEmpty() {
     10         return size() == 0;
     11     }
     12     public boolean contains(Object o) {
     13         Iterator<E> it = iterator();
     14         if (o==null) {
     15             while (it.hasNext())
     16                 if (it.next()==null)
     17                     return true;
     18         } else {
     19             while (it.hasNext())
     20                 if (o.equals(it.next()))
     21                     return true;
     22         }
     23         return false;
     24     }
     25     public Object[] toArray() {
     26         // Estimate size of array; be prepared to see more or fewer elements
     27         Object[] r = new Object[size()];
     28         Iterator<E> it = iterator();
     29         for (int i = 0; i < r.length; i++) {
     30             if (! it.hasNext()) // fewer elements than expected
     31                 return Arrays.copyOf(r, i);
     32             r[i] = it.next();
     33         }
     34         return it.hasNext() ? finishToArray(r, it) : r;
     35     }
     36     @SuppressWarnings("unchecked")
     37     public <T> T[] toArray(T[] a) {
     38         // Estimate size of array; be prepared to see more or fewer elements
     39         int size = size();
     40         T[] r = a.length >= size ? a :
     41                   (T[])java.lang.reflect.Array
     42                   .newInstance(a.getClass().getComponentType(), size);
     43         Iterator<E> it = iterator();
     44 
     45         for (int i = 0; i < r.length; i++) {
     46             if (! it.hasNext()) { // fewer elements than expected
     47                 if (a == r) {
     48                     r[i] = null; // null-terminate
     49                 } else if (a.length < i) {
     50                     return Arrays.copyOf(r, i);
     51                 } else {
     52                     System.arraycopy(r, 0, a, 0, i);
     53                     if (a.length > i) {
     54                         a[i] = null;
     55                     }
     56                 }
     57                 return a;
     58             }
     59             r[i] = (T)it.next();
     60         }
     61         // more elements than expected
     62         return it.hasNext() ? finishToArray(r, it) : r;
     63     }
     64 
     65     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
     66     @SuppressWarnings("unchecked")
     67     private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
     68         int i = r.length;
     69         while (it.hasNext()) {
     70             int cap = r.length;
     71             if (i == cap) {
     72                 int newCap = cap + (cap >> 1) + 1;
     73                 // overflow-conscious code
     74                 if (newCap - MAX_ARRAY_SIZE > 0)
     75                     newCap = hugeCapacity(cap + 1);
     76                 r = Arrays.copyOf(r, newCap);
     77             }
     78             r[i++] = (T)it.next();
     79         }
     80         // trim if overallocated
     81         return (i == r.length) ? r : Arrays.copyOf(r, i);
     82     }
     83 
     84     private static int hugeCapacity(int minCapacity) {
     85         if (minCapacity < 0) // overflow
     86             throw new OutOfMemoryError
     87                 ("Required array size too large");
     88         return (minCapacity > MAX_ARRAY_SIZE) ?
     89             Integer.MAX_VALUE :
     90             MAX_ARRAY_SIZE;
     91     }
     92     public boolean add(E e) {
     93         throw new UnsupportedOperationException();
     94     }
     95     public boolean remove(Object o) {
     96         Iterator<E> it = iterator();
     97         if (o==null) {
     98             while (it.hasNext()) {
     99                 if (it.next()==null) {
    100                     it.remove();
    101                     return true;
    102                 }
    103             }
    104         } else {
    105             while (it.hasNext()) {
    106                 if (o.equals(it.next())) {
    107                     it.remove();
    108                     return true;
    109                 }
    110             }
    111         }
    112         return false;
    113     }
    114     public boolean containsAll(Collection<?> c) {
    115         for (Object e : c)
    116             if (!contains(e))
    117                 return false;
    118         return true;
    119     }
    120     public boolean addAll(Collection<? extends E> c) {
    121         boolean modified = false;
    122         for (E e : c)
    123             if (add(e))
    124                 modified = true;
    125         return modified;
    126     }
    127     public boolean removeAll(Collection<?> c) {
    128         Objects.requireNonNull(c);
    129         boolean modified = false;
    130         Iterator<?> it = iterator();
    131         while (it.hasNext()) {
    132             if (c.contains(it.next())) {
    133                 it.remove();
    134                 modified = true;
    135             }
    136         }
    137         return modified;
    138     }
    139     public boolean retainAll(Collection<?> c) {
    140         Objects.requireNonNull(c);
    141         boolean modified = false;
    142         Iterator<E> it = iterator();
    143         while (it.hasNext()) {
    144             if (!c.contains(it.next())) {
    145                 it.remove();
    146                 modified = true;
    147             }
    148         }
    149         return modified;
    150     }
    151     public void clear() {
    152         Iterator<E> it = iterator();
    153         while (it.hasNext()) {
    154             it.next();
    155             it.remove();
    156         }
    157     }
    158     public String toString() {
    159         Iterator<E> it = iterator();
    160         if (! it.hasNext())
    161             return "[]";
    162 
    163         StringBuilder sb = new StringBuilder();
    164         sb.append('[');
    165         for (;;) {
    166             E e = it.next();
    167             sb.append(e == this ? "(this Collection)" : e);
    168             if (! it.hasNext())
    169                 return sb.append(']').toString();
    170             sb.append(',').append(' ');
    171         }
    172     }
    173 
    174 }
    View Code

     说明一下:

    (1)整体上来看,抽象类:AbstractCollection<E>实现了Collection接口,并且定义了接口中没有实现的方法体。

     (2)其中的: public abstract Iterator<E> iterator();  依然是沿用之前jdk版本的使用方式,当前抽象类没有给出具体的实现,在另外一个抽象类AbstractList中给出了具体实现:

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

     那么其中:new Itr()拿到的到底是什么呢?

    继续贴出jdk中的源码:

     1  private class Itr implements Iterator<E> {
     2         int cursor = 0;                    //下一个元素的索引下标
     3         int lastRet = -1;                //上一个被调用的元素下标
     4         int expectedModCount = modCount;
     5         public boolean hasNext() {
     6             return cursor != size();
     7         }
     8 
     9         public E next() {                //返回下一个元素
    10             checkForComodification();
    11             try {
    12                 int i = cursor;
    13                 E next = get(i);
    14                 lastRet = i;
    15                 cursor = i + 1;
    16                 return next;
    17             } catch (IndexOutOfBoundsException e) {
    18                 checkForComodification();
    19                 throw new NoSuchElementException();
    20             }
    21         }
    22 
    23         public void remove() {        //移除元素
    24             if (lastRet < 0)
    25                 throw new IllegalStateException();
    26             checkForComodification();
    27 
    28             try {
    29                 AbstractList.this.remove(lastRet);
    30                 if (lastRet < cursor)
    31                     cursor--;
    32                 lastRet = -1;
    33                 expectedModCount = modCount;
    34             } catch (IndexOutOfBoundsException e) {
    35                 throw new ConcurrentModificationException();
    36             }
    37         }
    38 
    39         final void checkForComodification() {
    40             if (modCount != expectedModCount)
    41                 throw new ConcurrentModificationException();
    42         }
    43     }

     总结一下:

      到目前为止,我们知道,如果只是想简单地获取集合的迭代器(非并行),可直接调用集合的iterator()方法即可,但是如果想要调用几何的并发的迭代器,则需要换一个JDK1.8新增进去的方法:

    1 default Stream<E> stream() {                //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据
    2         return StreamSupport.stream(spliterator(), false);//返回的流是顺序的
    3     }
    4     default Stream<E> parallelStream() {        //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据
    5         return StreamSupport.stream(spliterator(), true);//返回的流是并行的
    6     }

     5、看看抽象类:AbstractList<E>中定义了那些规则?

    贴上JDK1.8中的源码:

      1 package java.util;
      2 public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
      3    
      4     protected AbstractList() {
      5     }
      6     public boolean add(E e) {
      7         add(size(), e);
      8         return true;
      9     }
     10 
     11     abstract public E get(int index);
     12 
     13    
     14     public E set(int index, E element) {
     15         throw new UnsupportedOperationException();
     16     }
     17     public void add(int index, E element) {
     18         throw new UnsupportedOperationException();
     19     }
     20 
     21     public E remove(int index) {
     22         throw new UnsupportedOperationException();
     23     }
     24     public int indexOf(Object o) {
     25         ListIterator<E> it = listIterator();
     26         if (o==null) {
     27             while (it.hasNext())
     28                 if (it.next()==null)
     29                     return it.previousIndex();
     30         } else {
     31             while (it.hasNext())
     32                 if (o.equals(it.next()))
     33                     return it.previousIndex();
     34         }
     35         return -1;
     36     }
     37     public int lastIndexOf(Object o) {
     38         ListIterator<E> it = listIterator(size());
     39         if (o==null) {
     40             while (it.hasPrevious())
     41                 if (it.previous()==null)
     42                     return it.nextIndex();
     43         } else {
     44             while (it.hasPrevious())
     45                 if (o.equals(it.previous()))
     46                     return it.nextIndex();
     47         }
     48         return -1;
     49     }
     50 
     51     public void clear() {
     52         removeRange(0, size());
     53     }
     54     public boolean addAll(int index, Collection<? extends E> c) {
     55         rangeCheckForAdd(index);
     56         boolean modified = false;
     57         for (E e : c) {
     58             add(index++, e);
     59             modified = true;
     60         }
     61         return modified;
     62     }
     63     public Iterator<E> iterator() {
     64         return new Itr();
     65     }
     66     public ListIterator<E> listIterator() {
     67         return listIterator(0);
     68     }
     69     public ListIterator<E> listIterator(final int index) {
     70         rangeCheckForAdd(index);
     71 
     72         return new ListItr(index);
     73     }
     74 
     75     private class Itr implements Iterator<E> {
     76       
     77         int cursor = 0;
     78 
     79         
     80         int lastRet = -1;
     81 
     82        
     83         int expectedModCount = modCount;
     84 
     85         public boolean hasNext() {
     86             return cursor != size();
     87         }
     88 
     89         public E next() {
     90             checkForComodification();
     91             try {
     92                 int i = cursor;
     93                 E next = get(i);
     94                 lastRet = i;
     95                 cursor = i + 1;
     96                 return next;
     97             } catch (IndexOutOfBoundsException e) {
     98                 checkForComodification();
     99                 throw new NoSuchElementException();
    100             }
    101         }
    102 
    103         public void remove() {
    104             if (lastRet < 0)
    105                 throw new IllegalStateException();
    106             checkForComodification();
    107 
    108             try {
    109                 AbstractList.this.remove(lastRet);
    110                 if (lastRet < cursor)
    111                     cursor--;
    112                 lastRet = -1;
    113                 expectedModCount = modCount;
    114             } catch (IndexOutOfBoundsException e) {
    115                 throw new ConcurrentModificationException();
    116             }
    117         }
    118 
    119         final void checkForComodification() {
    120             if (modCount != expectedModCount)
    121                 throw new ConcurrentModificationException();
    122         }
    123     }
    124 
    125     private class ListItr extends Itr implements ListIterator<E> {
    126         ListItr(int index) {
    127             cursor = index;
    128         }
    129 
    130         public boolean hasPrevious() {
    131             return cursor != 0;
    132         }
    133 
    134         public E previous() {
    135             checkForComodification();
    136             try {
    137                 int i = cursor - 1;
    138                 E previous = get(i);
    139                 lastRet = cursor = i;
    140                 return previous;
    141             } catch (IndexOutOfBoundsException e) {
    142                 checkForComodification();
    143                 throw new NoSuchElementException();
    144             }
    145         }
    146 
    147         public int nextIndex() {
    148             return cursor;
    149         }
    150 
    151         public int previousIndex() {
    152             return cursor-1;
    153         }
    154 
    155         public void set(E e) {
    156             if (lastRet < 0)
    157                 throw new IllegalStateException();
    158             checkForComodification();
    159 
    160             try {
    161                 AbstractList.this.set(lastRet, e);
    162                 expectedModCount = modCount;
    163             } catch (IndexOutOfBoundsException ex) {
    164                 throw new ConcurrentModificationException();
    165             }
    166         }
    167 
    168         public void add(E e) {
    169             checkForComodification();
    170 
    171             try {
    172                 int i = cursor;
    173                 AbstractList.this.add(i, e);
    174                 lastRet = -1;
    175                 cursor = i + 1;
    176                 expectedModCount = modCount;
    177             } catch (IndexOutOfBoundsException ex) {
    178                 throw new ConcurrentModificationException();
    179             }
    180         }
    181     }
    182     public List<E> subList(int fromIndex, int toIndex) {
    183         return (this instanceof RandomAccess ?
    184                 new RandomAccessSubList<>(this, fromIndex, toIndex) :
    185                 new SubList<>(this, fromIndex, toIndex));
    186     }
    187     public boolean equals(Object o) {
    188         if (o == this)
    189             return true;
    190         if (!(o instanceof List))
    191             return false;
    192 
    193         ListIterator<E> e1 = listIterator();
    194         ListIterator<?> e2 = ((List<?>) o).listIterator();
    195         while (e1.hasNext() && e2.hasNext()) {
    196             E o1 = e1.next();
    197             Object o2 = e2.next();
    198             if (!(o1==null ? o2==null : o1.equals(o2)))
    199                 return false;
    200         }
    201         return !(e1.hasNext() || e2.hasNext());
    202     }
    203     public int hashCode() {
    204         int hashCode = 1;
    205         for (E e : this)
    206             hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    207         return hashCode;
    208     }
    209     protected void removeRange(int fromIndex, int toIndex) {
    210         ListIterator<E> it = listIterator(fromIndex);
    211         for (int i=0, n=toIndex-fromIndex; i<n; i++) {
    212             it.next();
    213             it.remove();
    214         }
    215     }
    216     protected transient int modCount = 0;
    217 
    218     private void rangeCheckForAdd(int index) {
    219         if (index < 0 || index > size())
    220             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    221     }
    222 
    223     private String outOfBoundsMsg(int index) {
    224         return "Index: "+index+", Size: "+size();
    225     }
    226 }
    227 
    228 class SubList<E> extends AbstractList<E> {
    229     private final AbstractList<E> l;
    230     private final int offset;
    231     private int size;
    232 
    233     SubList(AbstractList<E> list, int fromIndex, int toIndex) {
    234         if (fromIndex < 0)
    235             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
    236         if (toIndex > list.size())
    237             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
    238         if (fromIndex > toIndex)
    239             throw new IllegalArgumentException("fromIndex(" + fromIndex +
    240                                                ") > toIndex(" + toIndex + ")");
    241         l = list;
    242         offset = fromIndex;
    243         size = toIndex - fromIndex;
    244         this.modCount = l.modCount;
    245     }
    246 
    247     public E set(int index, E element) {
    248         rangeCheck(index);
    249         checkForComodification();
    250         return l.set(index+offset, element);
    251     }
    252 
    253     public E get(int index) {
    254         rangeCheck(index);
    255         checkForComodification();
    256         return l.get(index+offset);
    257     }
    258 
    259     public int size() {
    260         checkForComodification();
    261         return size;
    262     }
    263 
    264     public void add(int index, E element) {
    265         rangeCheckForAdd(index);
    266         checkForComodification();
    267         l.add(index+offset, element);
    268         this.modCount = l.modCount;
    269         size++;
    270     }
    271 
    272     public E remove(int index) {
    273         rangeCheck(index);
    274         checkForComodification();
    275         E result = l.remove(index+offset);
    276         this.modCount = l.modCount;
    277         size--;
    278         return result;
    279     }
    280 
    281     protected void removeRange(int fromIndex, int toIndex) {
    282         checkForComodification();
    283         l.removeRange(fromIndex+offset, toIndex+offset);
    284         this.modCount = l.modCount;
    285         size -= (toIndex-fromIndex);
    286     }
    287 
    288     public boolean addAll(Collection<? extends E> c) {
    289         return addAll(size, c);
    290     }
    291 
    292     public boolean addAll(int index, Collection<? extends E> c) {
    293         rangeCheckForAdd(index);
    294         int cSize = c.size();
    295         if (cSize==0)
    296             return false;
    297 
    298         checkForComodification();
    299         l.addAll(offset+index, c);
    300         this.modCount = l.modCount;
    301         size += cSize;
    302         return true;
    303     }
    304 
    305     public Iterator<E> iterator() {
    306         return listIterator();
    307     }
    308 
    309     public ListIterator<E> listIterator(final int index) {
    310         checkForComodification();
    311         rangeCheckForAdd(index);
    312 
    313         return new ListIterator<E>() {
    314             private final ListIterator<E> i = l.listIterator(index+offset);
    315 
    316             public boolean hasNext() {
    317                 return nextIndex() < size;
    318             }
    319 
    320             public E next() {
    321                 if (hasNext())
    322                     return i.next();
    323                 else
    324                     throw new NoSuchElementException();
    325             }
    326 
    327             public boolean hasPrevious() {
    328                 return previousIndex() >= 0;
    329             }
    330 
    331             public E previous() {
    332                 if (hasPrevious())
    333                     return i.previous();
    334                 else
    335                     throw new NoSuchElementException();
    336             }
    337 
    338             public int nextIndex() {
    339                 return i.nextIndex() - offset;
    340             }
    341 
    342             public int previousIndex() {
    343                 return i.previousIndex() - offset;
    344             }
    345 
    346             public void remove() {
    347                 i.remove();
    348                 SubList.this.modCount = l.modCount;
    349                 size--;
    350             }
    351 
    352             public void set(E e) {
    353                 i.set(e);
    354             }
    355 
    356             public void add(E e) {
    357                 i.add(e);
    358                 SubList.this.modCount = l.modCount;
    359                 size++;
    360             }
    361         };
    362     }
    363 
    364     public List<E> subList(int fromIndex, int toIndex) {
    365         return new SubList<>(this, fromIndex, toIndex);
    366     }
    367 
    368     private void rangeCheck(int index) {
    369         if (index < 0 || index >= size)
    370             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    371     }
    372 
    373     private void rangeCheckForAdd(int index) {
    374         if (index < 0 || index > size)
    375             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    376     }
    377 
    378     private String outOfBoundsMsg(int index) {
    379         return "Index: "+index+", Size: "+size;
    380     }
    381 
    382     private void checkForComodification() {
    383         if (this.modCount != l.modCount)
    384             throw new ConcurrentModificationException();
    385     }
    386 }
    387 
    388 class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    389     RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
    390         super(list, fromIndex, toIndex);
    391     }
    392 
    393     public List<E> subList(int fromIndex, int toIndex) {
    394         return new RandomAccessSubList<>(this, fromIndex, toIndex);
    395     }
    396 }
    View Code

    简单看一下抽象类的结构图:

     说明一下:

    这个抽象类中存在:抽象方法的声明,一些具体方法的实现,也内置了一些内部类:

      private class Itr implements Iterator<E> {}

      private class ListItr extends Itr implements ListIterator<E> {}

    以上2两种迭代器丰富了AbstractList这个抽象类的迭代方式,以后继承这个抽象类的子类也可以重写会直接复用,为子类提供了多样化的功能。

    一直在说:以上的接口或者抽象类只是在定义集合的规则,有些人就会有疑惑了,明明这个接口或者抽象类中也有一些实现了功能的方法啊。

    其实对于一个集合来说,最重要的是什么?是如何把数据存进去,存在哪里,如何存放,如何取出来,如何存放到一个迭代器中(我们都知道是以链表的形式存放),那么从上面的接口或者抽象类中,我并没有发现:

    (1)数据的存放的位置(数组,list集合中维护的是数组)。

    (2)数据如何存放在迭代器中的链表。

    以上这2中核心实现的代码,并不存在于上述的接口和抽象类中,所以我们接着往下看,继续去寻找答案!!!

    6、看看接口:List<E>中定义了那些规则?

    贴上JDK1.8中的源码:

      1 package java.util;
      2 import java.util.function.UnaryOperator;
      3 public interface List<E> extends Collection<E> {
      4     // Query Operations
      5 
      6     /**
      7      * Returns the number of elements in this list.  If this list contains
      8      * more than <tt>Integer.MAX_VALUE</tt> elements, returns
      9      * <tt>Integer.MAX_VALUE</tt>.
     10      *
     11      * @return the number of elements in this list
     12      */
     13     int size();
     14 
     15     /**
     16      * Returns <tt>true</tt> if this list contains no elements.
     17      *
     18      * @return <tt>true</tt> if this list contains no elements
     19      */
     20     boolean isEmpty();
     21 
     22     /**
     23      * Returns <tt>true</tt> if this list contains the specified element.
     24      * More formally, returns <tt>true</tt> if and only if this list contains
     25      * at least one element <tt>e</tt> such that
     26      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     27      *
     28      * @param o element whose presence in this list is to be tested
     29      * @return <tt>true</tt> if this list contains the specified element
     30      * @throws ClassCastException if the type of the specified element
     31      *         is incompatible with this list
     32      * (<a href="Collection.html#optional-restrictions">optional</a>)
     33      * @throws NullPointerException if the specified element is null and this
     34      *         list does not permit null elements
     35      * (<a href="Collection.html#optional-restrictions">optional</a>)
     36      */
     37     boolean contains(Object o);
     38 
     39     /**
     40      * Returns an iterator over the elements in this list in proper sequence.
     41      *
     42      * @return an iterator over the elements in this list in proper sequence
     43      */
     44     Iterator<E> iterator();
     45 
     46     /**
     47      * Returns an array containing all of the elements in this list in proper
     48      * sequence (from first to last element).
     49      *
     50      * <p>The returned array will be "safe" in that no references to it are
     51      * maintained by this list.  (In other words, this method must
     52      * allocate a new array even if this list is backed by an array).
     53      * The caller is thus free to modify the returned array.
     54      *
     55      * <p>This method acts as bridge between array-based and collection-based
     56      * APIs.
     57      *
     58      * @return an array containing all of the elements in this list in proper
     59      *         sequence
     60      * @see Arrays#asList(Object[])
     61      */
     62     Object[] toArray();
     63 
     64     /**
     65      * Returns an array containing all of the elements in this list in
     66      * proper sequence (from first to last element); the runtime type of
     67      * the returned array is that of the specified array.  If the list fits
     68      * in the specified array, it is returned therein.  Otherwise, a new
     69      * array is allocated with the runtime type of the specified array and
     70      * the size of this list.
     71      *
     72      * <p>If the list fits in the specified array with room to spare (i.e.,
     73      * the array has more elements than the list), the element in the array
     74      * immediately following the end of the list is set to <tt>null</tt>.
     75      * (This is useful in determining the length of the list <i>only</i> if
     76      * the caller knows that the list does not contain any null elements.)
     77      *
     78      * <p>Like the {@link #toArray()} method, this method acts as bridge between
     79      * array-based and collection-based APIs.  Further, this method allows
     80      * precise control over the runtime type of the output array, and may,
     81      * under certain circumstances, be used to save allocation costs.
     82      *
     83      * <p>Suppose <tt>x</tt> is a list known to contain only strings.
     84      * The following code can be used to dump the list into a newly
     85      * allocated array of <tt>String</tt>:
     86      *
     87      * <pre>{@code
     88      *     String[] y = x.toArray(new String[0]);
     89      * }</pre>
     90      *
     91      * Note that <tt>toArray(new Object[0])</tt> is identical in function to
     92      * <tt>toArray()</tt>.
     93      *
     94      * @param a the array into which the elements of this list are to
     95      *          be stored, if it is big enough; otherwise, a new array of the
     96      *          same runtime type is allocated for this purpose.
     97      * @return an array containing the elements of this list
     98      * @throws ArrayStoreException if the runtime type of the specified array
     99      *         is not a supertype of the runtime type of every element in
    100      *         this list
    101      * @throws NullPointerException if the specified array is null
    102      */
    103     <T> T[] toArray(T[] a);
    104 
    105 
    106     // Modification Operations
    107 
    108     /**
    109      * Appends the specified element to the end of this list (optional
    110      * operation).
    111      *
    112      * <p>Lists that support this operation may place limitations on what
    113      * elements may be added to this list.  In particular, some
    114      * lists will refuse to add null elements, and others will impose
    115      * restrictions on the type of elements that may be added.  List
    116      * classes should clearly specify in their documentation any restrictions
    117      * on what elements may be added.
    118      *
    119      * @param e element to be appended to this list
    120      * @return <tt>true</tt> (as specified by {@link Collection#add})
    121      * @throws UnsupportedOperationException if the <tt>add</tt> operation
    122      *         is not supported by this list
    123      * @throws ClassCastException if the class of the specified element
    124      *         prevents it from being added to this list
    125      * @throws NullPointerException if the specified element is null and this
    126      *         list does not permit null elements
    127      * @throws IllegalArgumentException if some property of this element
    128      *         prevents it from being added to this list
    129      */
    130     boolean add(E e);
    131 
    132     /**
    133      * Removes the first occurrence of the specified element from this list,
    134      * if it is present (optional operation).  If this list does not contain
    135      * the element, it is unchanged.  More formally, removes the element with
    136      * the lowest index <tt>i</tt> such that
    137      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
    138      * (if such an element exists).  Returns <tt>true</tt> if this list
    139      * contained the specified element (or equivalently, if this list changed
    140      * as a result of the call).
    141      *
    142      * @param o element to be removed from this list, if present
    143      * @return <tt>true</tt> if this list contained the specified element
    144      * @throws ClassCastException if the type of the specified element
    145      *         is incompatible with this list
    146      * (<a href="Collection.html#optional-restrictions">optional</a>)
    147      * @throws NullPointerException if the specified element is null and this
    148      *         list does not permit null elements
    149      * (<a href="Collection.html#optional-restrictions">optional</a>)
    150      * @throws UnsupportedOperationException if the <tt>remove</tt> operation
    151      *         is not supported by this list
    152      */
    153     boolean remove(Object o);
    154 
    155 
    156     // Bulk Modification Operations
    157 
    158     /**
    159      * Returns <tt>true</tt> if this list contains all of the elements of the
    160      * specified collection.
    161      *
    162      * @param  c collection to be checked for containment in this list
    163      * @return <tt>true</tt> if this list contains all of the elements of the
    164      *         specified collection
    165      * @throws ClassCastException if the types of one or more elements
    166      *         in the specified collection are incompatible with this
    167      *         list
    168      * (<a href="Collection.html#optional-restrictions">optional</a>)
    169      * @throws NullPointerException if the specified collection contains one
    170      *         or more null elements and this list does not permit null
    171      *         elements
    172      *         (<a href="Collection.html#optional-restrictions">optional</a>),
    173      *         or if the specified collection is null
    174      * @see #contains(Object)
    175      */
    176     boolean containsAll(Collection<?> c);
    177 
    178     /**
    179      * Appends all of the elements in the specified collection to the end of
    180      * this list, in the order that they are returned by the specified
    181      * collection's iterator (optional operation).  The behavior of this
    182      * operation is undefined if the specified collection is modified while
    183      * the operation is in progress.  (Note that this will occur if the
    184      * specified collection is this list, and it's nonempty.)
    185      *
    186      * @param c collection containing elements to be added to this list
    187      * @return <tt>true</tt> if this list changed as a result of the call
    188      * @throws UnsupportedOperationException if the <tt>addAll</tt> operation
    189      *         is not supported by this list
    190      * @throws ClassCastException if the class of an element of the specified
    191      *         collection prevents it from being added to this list
    192      * @throws NullPointerException if the specified collection contains one
    193      *         or more null elements and this list does not permit null
    194      *         elements, or if the specified collection is null
    195      * @throws IllegalArgumentException if some property of an element of the
    196      *         specified collection prevents it from being added to this list
    197      * @see #add(Object)
    198      */
    199     boolean addAll(Collection<? extends E> c);
    200 
    201     /**
    202      * Inserts all of the elements in the specified collection into this
    203      * list at the specified position (optional operation).  Shifts the
    204      * element currently at that position (if any) and any subsequent
    205      * elements to the right (increases their indices).  The new elements
    206      * will appear in this list in the order that they are returned by the
    207      * specified collection's iterator.  The behavior of this operation is
    208      * undefined if the specified collection is modified while the
    209      * operation is in progress.  (Note that this will occur if the specified
    210      * collection is this list, and it's nonempty.)
    211      *
    212      * @param index index at which to insert the first element from the
    213      *              specified collection
    214      * @param c collection containing elements to be added to this list
    215      * @return <tt>true</tt> if this list changed as a result of the call
    216      * @throws UnsupportedOperationException if the <tt>addAll</tt> operation
    217      *         is not supported by this list
    218      * @throws ClassCastException if the class of an element of the specified
    219      *         collection prevents it from being added to this list
    220      * @throws NullPointerException if the specified collection contains one
    221      *         or more null elements and this list does not permit null
    222      *         elements, or if the specified collection is null
    223      * @throws IllegalArgumentException if some property of an element of the
    224      *         specified collection prevents it from being added to this list
    225      * @throws IndexOutOfBoundsException if the index is out of range
    226      *         (<tt>index &lt; 0 || index &gt; size()</tt>)
    227      */
    228     boolean addAll(int index, Collection<? extends E> c);
    229 
    230     /**
    231      * Removes from this list all of its elements that are contained in the
    232      * specified collection (optional operation).
    233      *
    234      * @param c collection containing elements to be removed from this list
    235      * @return <tt>true</tt> if this list changed as a result of the call
    236      * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation
    237      *         is not supported by this list
    238      * @throws ClassCastException if the class of an element of this list
    239      *         is incompatible with the specified collection
    240      * (<a href="Collection.html#optional-restrictions">optional</a>)
    241      * @throws NullPointerException if this list contains a null element and the
    242      *         specified collection does not permit null elements
    243      *         (<a href="Collection.html#optional-restrictions">optional</a>),
    244      *         or if the specified collection is null
    245      * @see #remove(Object)
    246      * @see #contains(Object)
    247      */
    248     boolean removeAll(Collection<?> c);
    249 
    250     /**
    251      * Retains only the elements in this list that are contained in the
    252      * specified collection (optional operation).  In other words, removes
    253      * from this list all of its elements that are not contained in the
    254      * specified collection.
    255      *
    256      * @param c collection containing elements to be retained in this list
    257      * @return <tt>true</tt> if this list changed as a result of the call
    258      * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation
    259      *         is not supported by this list
    260      * @throws ClassCastException if the class of an element of this list
    261      *         is incompatible with the specified collection
    262      * (<a href="Collection.html#optional-restrictions">optional</a>)
    263      * @throws NullPointerException if this list contains a null element and the
    264      *         specified collection does not permit null elements
    265      *         (<a href="Collection.html#optional-restrictions">optional</a>),
    266      *         or if the specified collection is null
    267      * @see #remove(Object)
    268      * @see #contains(Object)
    269      */
    270     boolean retainAll(Collection<?> c);
    271 
    272     /**
    273      * Replaces each element of this list with the result of applying the
    274      * operator to that element.  Errors or runtime exceptions thrown by
    275      * the operator are relayed to the caller.
    276      *
    277      * @implSpec
    278      * The default implementation is equivalent to, for this {@code list}:
    279      * <pre>{@code
    280      *     final ListIterator<E> li = list.listIterator();
    281      *     while (li.hasNext()) {
    282      *         li.set(operator.apply(li.next()));
    283      *     }
    284      * }</pre>
    285      *
    286      * If the list's list-iterator does not support the {@code set} operation
    287      * then an {@code UnsupportedOperationException} will be thrown when
    288      * replacing the first element.
    289      *
    290      * @param operator the operator to apply to each element
    291      * @throws UnsupportedOperationException if this list is unmodifiable.
    292      *         Implementations may throw this exception if an element
    293      *         cannot be replaced or if, in general, modification is not
    294      *         supported
    295      * @throws NullPointerException if the specified operator is null or
    296      *         if the operator result is a null value and this list does
    297      *         not permit null elements
    298      *         (<a href="Collection.html#optional-restrictions">optional</a>)
    299      * @since 1.8
    300      */
    301     default void replaceAll(UnaryOperator<E> operator) {
    302         Objects.requireNonNull(operator);
    303         final ListIterator<E> li = this.listIterator();
    304         while (li.hasNext()) {
    305             li.set(operator.apply(li.next()));
    306         }
    307     }
    308 
    309     /**
    310      * Sorts this list according to the order induced by the specified
    311      * {@link Comparator}.
    312      *
    313      * <p>All elements in this list must be <i>mutually comparable</i> using the
    314      * specified comparator (that is, {@code c.compare(e1, e2)} must not throw
    315      * a {@code ClassCastException} for any elements {@code e1} and {@code e2}
    316      * in the list).
    317      *
    318      * <p>If the specified comparator is {@code null} then all elements in this
    319      * list must implement the {@link Comparable} interface and the elements'
    320      * {@linkplain Comparable natural ordering} should be used.
    321      *
    322      * <p>This list must be modifiable, but need not be resizable.
    323      *
    324      * @implSpec
    325      * The default implementation obtains an array containing all elements in
    326      * this list, sorts the array, and iterates over this list resetting each
    327      * element from the corresponding position in the array. (This avoids the
    328      * n<sup>2</sup> log(n) performance that would result from attempting
    329      * to sort a linked list in place.)
    330      *
    331      * @implNote
    332      * This implementation is a stable, adaptive, iterative mergesort that
    333      * requires far fewer than n lg(n) comparisons when the input array is
    334      * partially sorted, while offering the performance of a traditional
    335      * mergesort when the input array is randomly ordered.  If the input array
    336      * is nearly sorted, the implementation requires approximately n
    337      * comparisons.  Temporary storage requirements vary from a small constant
    338      * for nearly sorted input arrays to n/2 object references for randomly
    339      * ordered input arrays.
    340      *
    341      * <p>The implementation takes equal advantage of ascending and
    342      * descending order in its input array, and can take advantage of
    343      * ascending and descending order in different parts of the same
    344      * input array.  It is well-suited to merging two or more sorted arrays:
    345      * simply concatenate the arrays and sort the resulting array.
    346      *
    347      * <p>The implementation was adapted from Tim Peters's list sort for Python
    348      * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
    349      * TimSort</a>).  It uses techniques from Peter McIlroy's "Optimistic
    350      * Sorting and Information Theoretic Complexity", in Proceedings of the
    351      * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
    352      * January 1993.
    353      *
    354      * @param c the {@code Comparator} used to compare list elements.
    355      *          A {@code null} value indicates that the elements'
    356      *          {@linkplain Comparable natural ordering} should be used
    357      * @throws ClassCastException if the list contains elements that are not
    358      *         <i>mutually comparable</i> using the specified comparator
    359      * @throws UnsupportedOperationException if the list's list-iterator does
    360      *         not support the {@code set} operation
    361      * @throws IllegalArgumentException
    362      *         (<a href="Collection.html#optional-restrictions">optional</a>)
    363      *         if the comparator is found to violate the {@link Comparator}
    364      *         contract
    365      * @since 1.8
    366      */
    367     @SuppressWarnings({"unchecked", "rawtypes"})
    368     default void sort(Comparator<? super E> c) {
    369         Object[] a = this.toArray();
    370         Arrays.sort(a, (Comparator) c);
    371         ListIterator<E> i = this.listIterator();
    372         for (Object e : a) {
    373             i.next();
    374             i.set((E) e);
    375         }
    376     }
    377 
    378     /**
    379      * Removes all of the elements from this list (optional operation).
    380      * The list will be empty after this call returns.
    381      *
    382      * @throws UnsupportedOperationException if the <tt>clear</tt> operation
    383      *         is not supported by this list
    384      */
    385     void clear();
    386 
    387 
    388     // Comparison and hashing
    389 
    390     /**
    391      * Compares the specified object with this list for equality.  Returns
    392      * <tt>true</tt> if and only if the specified object is also a list, both
    393      * lists have the same size, and all corresponding pairs of elements in
    394      * the two lists are <i>equal</i>.  (Two elements <tt>e1</tt> and
    395      * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
    396      * e1.equals(e2))</tt>.)  In other words, two lists are defined to be
    397      * equal if they contain the same elements in the same order.  This
    398      * definition ensures that the equals method works properly across
    399      * different implementations of the <tt>List</tt> interface.
    400      *
    401      * @param o the object to be compared for equality with this list
    402      * @return <tt>true</tt> if the specified object is equal to this list
    403      */
    404     boolean equals(Object o);
    405 
    406     /**
    407      * Returns the hash code value for this list.  The hash code of a list
    408      * is defined to be the result of the following calculation:
    409      * <pre>{@code
    410      *     int hashCode = 1;
    411      *     for (E e : list)
    412      *         hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    413      * }</pre>
    414      * This ensures that <tt>list1.equals(list2)</tt> implies that
    415      * <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists,
    416      * <tt>list1</tt> and <tt>list2</tt>, as required by the general
    417      * contract of {@link Object#hashCode}.
    418      *
    419      * @return the hash code value for this list
    420      * @see Object#equals(Object)
    421      * @see #equals(Object)
    422      */
    423     int hashCode();
    424 
    425 
    426     // Positional Access Operations
    427 
    428     /**
    429      * Returns the element at the specified position in this list.
    430      *
    431      * @param index index of the element to return
    432      * @return the element at the specified position in this list
    433      * @throws IndexOutOfBoundsException if the index is out of range
    434      *         (<tt>index &lt; 0 || index &gt;= size()</tt>)
    435      */
    436     E get(int index);
    437 
    438     /**
    439      * Replaces the element at the specified position in this list with the
    440      * specified element (optional operation).
    441      *
    442      * @param index index of the element to replace
    443      * @param element element to be stored at the specified position
    444      * @return the element previously at the specified position
    445      * @throws UnsupportedOperationException if the <tt>set</tt> operation
    446      *         is not supported by this list
    447      * @throws ClassCastException if the class of the specified element
    448      *         prevents it from being added to this list
    449      * @throws NullPointerException if the specified element is null and
    450      *         this list does not permit null elements
    451      * @throws IllegalArgumentException if some property of the specified
    452      *         element prevents it from being added to this list
    453      * @throws IndexOutOfBoundsException if the index is out of range
    454      *         (<tt>index &lt; 0 || index &gt;= size()</tt>)
    455      */
    456     E set(int index, E element);
    457 
    458     /**
    459      * Inserts the specified element at the specified position in this list
    460      * (optional operation).  Shifts the element currently at that position
    461      * (if any) and any subsequent elements to the right (adds one to their
    462      * indices).
    463      *
    464      * @param index index at which the specified element is to be inserted
    465      * @param element element to be inserted
    466      * @throws UnsupportedOperationException if the <tt>add</tt> operation
    467      *         is not supported by this list
    468      * @throws ClassCastException if the class of the specified element
    469      *         prevents it from being added to this list
    470      * @throws NullPointerException if the specified element is null and
    471      *         this list does not permit null elements
    472      * @throws IllegalArgumentException if some property of the specified
    473      *         element prevents it from being added to this list
    474      * @throws IndexOutOfBoundsException if the index is out of range
    475      *         (<tt>index &lt; 0 || index &gt; size()</tt>)
    476      */
    477     void add(int index, E element);
    478 
    479     /**
    480      * Removes the element at the specified position in this list (optional
    481      * operation).  Shifts any subsequent elements to the left (subtracts one
    482      * from their indices).  Returns the element that was removed from the
    483      * list.
    484      *
    485      * @param index the index of the element to be removed
    486      * @return the element previously at the specified position
    487      * @throws UnsupportedOperationException if the <tt>remove</tt> operation
    488      *         is not supported by this list
    489      * @throws IndexOutOfBoundsException if the index is out of range
    490      *         (<tt>index &lt; 0 || index &gt;= size()</tt>)
    491      */
    492     E remove(int index);
    493 
    494 
    495     // Search Operations
    496 
    497     /**
    498      * Returns the index of the first occurrence of the specified element
    499      * in this list, or -1 if this list does not contain the element.
    500      * More formally, returns the lowest index <tt>i</tt> such that
    501      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
    502      * or -1 if there is no such index.
    503      *
    504      * @param o element to search for
    505      * @return the index of the first occurrence of the specified element in
    506      *         this list, or -1 if this list does not contain the element
    507      * @throws ClassCastException if the type of the specified element
    508      *         is incompatible with this list
    509      *         (<a href="Collection.html#optional-restrictions">optional</a>)
    510      * @throws NullPointerException if the specified element is null and this
    511      *         list does not permit null elements
    512      *         (<a href="Collection.html#optional-restrictions">optional</a>)
    513      */
    514     int indexOf(Object o);
    515 
    516     /**
    517      * Returns the index of the last occurrence of the specified element
    518      * in this list, or -1 if this list does not contain the element.
    519      * More formally, returns the highest index <tt>i</tt> such that
    520      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
    521      * or -1 if there is no such index.
    522      *
    523      * @param o element to search for
    524      * @return the index of the last occurrence of the specified element in
    525      *         this list, or -1 if this list does not contain the element
    526      * @throws ClassCastException if the type of the specified element
    527      *         is incompatible with this list
    528      *         (<a href="Collection.html#optional-restrictions">optional</a>)
    529      * @throws NullPointerException if the specified element is null and this
    530      *         list does not permit null elements
    531      *         (<a href="Collection.html#optional-restrictions">optional</a>)
    532      */
    533     int lastIndexOf(Object o);
    534 
    535 
    536     // List Iterators
    537 
    538     /**
    539      * Returns a list iterator over the elements in this list (in proper
    540      * sequence).
    541      *
    542      * @return a list iterator over the elements in this list (in proper
    543      *         sequence)
    544      */
    545     ListIterator<E> listIterator();
    546 
    547     /**
    548      * Returns a list iterator over the elements in this list (in proper
    549      * sequence), starting at the specified position in the list.
    550      * The specified index indicates the first element that would be
    551      * returned by an initial call to {@link ListIterator#next next}.
    552      * An initial call to {@link ListIterator#previous previous} would
    553      * return the element with the specified index minus one.
    554      *
    555      * @param index index of the first element to be returned from the
    556      *        list iterator (by a call to {@link ListIterator#next next})
    557      * @return a list iterator over the elements in this list (in proper
    558      *         sequence), starting at the specified position in the list
    559      * @throws IndexOutOfBoundsException if the index is out of range
    560      *         ({@code index < 0 || index > size()})
    561      */
    562     ListIterator<E> listIterator(int index);
    563 
    564     // View
    565 
    566     /**
    567      * Returns a view of the portion of this list between the specified
    568      * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.  (If
    569      * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
    570      * empty.)  The returned list is backed by this list, so non-structural
    571      * changes in the returned list are reflected in this list, and vice-versa.
    572      * The returned list supports all of the optional list operations supported
    573      * by this list.<p>
    574      *
    575      * This method eliminates the need for explicit range operations (of
    576      * the sort that commonly exist for arrays).  Any operation that expects
    577      * a list can be used as a range operation by passing a subList view
    578      * instead of a whole list.  For example, the following idiom
    579      * removes a range of elements from a list:
    580      * <pre>{@code
    581      *      list.subList(from, to).clear();
    582      * }</pre>
    583      * Similar idioms may be constructed for <tt>indexOf</tt> and
    584      * <tt>lastIndexOf</tt>, and all of the algorithms in the
    585      * <tt>Collections</tt> class can be applied to a subList.<p>
    586      *
    587      * The semantics of the list returned by this method become undefined if
    588      * the backing list (i.e., this list) is <i>structurally modified</i> in
    589      * any way other than via the returned list.  (Structural modifications are
    590      * those that change the size of this list, or otherwise perturb it in such
    591      * a fashion that iterations in progress may yield incorrect results.)
    592      *
    593      * @param fromIndex low endpoint (inclusive) of the subList
    594      * @param toIndex high endpoint (exclusive) of the subList
    595      * @return a view of the specified range within this list
    596      * @throws IndexOutOfBoundsException for an illegal endpoint index value
    597      *         (<tt>fromIndex &lt; 0 || toIndex &gt; size ||
    598      *         fromIndex &gt; toIndex</tt>)
    599      */
    600     List<E> subList(int fromIndex, int toIndex);
    601 
    602     /**
    603      * Creates a {@link Spliterator} over the elements in this list.
    604      *
    605      * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
    606      * {@link Spliterator#ORDERED}.  Implementations should document the
    607      * reporting of additional characteristic values.
    608      *
    609      * @implSpec
    610      * The default implementation creates a
    611      * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
    612      * from the list's {@code Iterator}.  The spliterator inherits the
    613      * <em>fail-fast</em> properties of the list's iterator.
    614      *
    615      * @implNote
    616      * The created {@code Spliterator} additionally reports
    617      * {@link Spliterator#SUBSIZED}.
    618      *
    619      * @return a {@code Spliterator} over the elements in this list
    620      * @since 1.8
    621      */
    622     @Override
    623     default Spliterator<E> spliterator() {
    624         return Spliterators.spliterator(this, Spliterator.ORDERED);
    625     }
    626 }
    View Code

     简单看一下抽象类的结构图:

    说明一下:

    从源码和抽象类的结构图中,同样可以看到:

    (1)List接口中没有说明集合数据是存放在哪里的?只是声明了一些集合操作的方法。、

    (2)List接口中没有看到迭代器是如何获取集合数据并存放到链表中的:如下:

    ListIterator<E> listIterator();
    ListIterator<E> listIterator(int index);

    所以想要探明究竟,就只能继续往下看,层层往下,直到ArrayList实现子类。

     7、看看实现类:ArrayList<E>是如何实现集合功能的?

    贴上JDK1.8中的源码:(内容有点多,会在下面捡重要的说明一下)

       1 /*
       2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
       3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
       4  *
       5  *
       6  *
       7  *
       8  *
       9  *
      10  *
      11  *
      12  *
      13  *
      14  *
      15  *
      16  *
      17  *
      18  *
      19  *
      20  *
      21  *
      22  *
      23  *
      24  */
      25 
      26 package java.util;
      27 
      28 import java.util.function.Consumer;
      29 import java.util.function.Predicate;
      30 import java.util.function.UnaryOperator;
      31 
      32 /**
      33  * Resizable-array implementation of the <tt>List</tt> interface.  Implements
      34  * all optional list operations, and permits all elements, including
      35  * <tt>null</tt>.  In addition to implementing the <tt>List</tt> interface,
      36  * this class provides methods to manipulate the size of the array that is
      37  * used internally to store the list.  (This class is roughly equivalent to
      38  * <tt>Vector</tt>, except that it is unsynchronized.)
      39  *
      40  * <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
      41  * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
      42  * time.  The <tt>add</tt> operation runs in <i>amortized constant time</i>,
      43  * that is, adding n elements requires O(n) time.  All of the other operations
      44  * run in linear time (roughly speaking).  The constant factor is low compared
      45  * to that for the <tt>LinkedList</tt> implementation.
      46  *
      47  * <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>.  The capacity is
      48  * the size of the array used to store the elements in the list.  It is always
      49  * at least as large as the list size.  As elements are added to an ArrayList,
      50  * its capacity grows automatically.  The details of the growth policy are not
      51  * specified beyond the fact that adding an element has constant amortized
      52  * time cost.
      53  *
      54  * <p>An application can increase the capacity of an <tt>ArrayList</tt> instance
      55  * before adding a large number of elements using the <tt>ensureCapacity</tt>
      56  * operation.  This may reduce the amount of incremental reallocation.
      57  *
      58  * <p><strong>Note that this implementation is not synchronized.</strong>
      59  * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
      60  * and at least one of the threads modifies the list structurally, it
      61  * <i>must</i> be synchronized externally.  (A structural modification is
      62  * any operation that adds or deletes one or more elements, or explicitly
      63  * resizes the backing array; merely setting the value of an element is not
      64  * a structural modification.)  This is typically accomplished by
      65  * synchronizing on some object that naturally encapsulates the list.
      66  *
      67  * If no such object exists, the list should be "wrapped" using the
      68  * {@link Collections#synchronizedList Collections.synchronizedList}
      69  * method.  This is best done at creation time, to prevent accidental
      70  * unsynchronized access to the list:<pre>
      71  *   List list = Collections.synchronizedList(new ArrayList(...));</pre>
      72  *
      73  * <p><a name="fail-fast">
      74  * The iterators returned by this class's {@link #iterator() iterator} and
      75  * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:</a>
      76  * if the list is structurally modified at any time after the iterator is
      77  * created, in any way except through the iterator's own
      78  * {@link ListIterator#remove() remove} or
      79  * {@link ListIterator#add(Object) add} methods, the iterator will throw a
      80  * {@link ConcurrentModificationException}.  Thus, in the face of
      81  * concurrent modification, the iterator fails quickly and cleanly, rather
      82  * than risking arbitrary, non-deterministic behavior at an undetermined
      83  * time in the future.
      84  *
      85  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
      86  * as it is, generally speaking, impossible to make any hard guarantees in the
      87  * presence of unsynchronized concurrent modification.  Fail-fast iterators
      88  * throw {@code ConcurrentModificationException} on a best-effort basis.
      89  * Therefore, it would be wrong to write a program that depended on this
      90  * exception for its correctness:  <i>the fail-fast behavior of iterators
      91  * should be used only to detect bugs.</i>
      92  *
      93  * <p>This class is a member of the
      94  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
      95  * Java Collections Framework</a>.
      96  *
      97  * @author  Josh Bloch
      98  * @author  Neal Gafter
      99  * @see     Collection
     100  * @see     List
     101  * @see     LinkedList
     102  * @see     Vector
     103  * @since   1.2
     104  */
     105 
     106 public class ArrayList<E> extends AbstractList<E>
     107         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
     108 {
     109     private static final long serialVersionUID = 8683452581122892189L;
     110 
     111     /**
     112      * Default initial capacity.
     113      */
     114     private static final int DEFAULT_CAPACITY = 10;
     115 
     116     /**
     117      * Shared empty array instance used for empty instances.
     118      */
     119     private static final Object[] EMPTY_ELEMENTDATA = {};
     120 
     121     /**
     122      * Shared empty array instance used for default sized empty instances. We
     123      * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     124      * first element is added.
     125      */
     126     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
     127 
     128     /**
     129      * The array buffer into which the elements of the ArrayList are stored.
     130      * The capacity of the ArrayList is the length of this array buffer. Any
     131      * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     132      * will be expanded to DEFAULT_CAPACITY when the first element is added.
     133      */
     134     transient Object[] elementData; // non-private to simplify nested class access
     135 
     136     /**
     137      * The size of the ArrayList (the number of elements it contains).
     138      *
     139      * @serial
     140      */
     141     private int size;
     142 
     143     /**
     144      * Constructs an empty list with the specified initial capacity.
     145      *
     146      * @param  initialCapacity  the initial capacity of the list
     147      * @throws IllegalArgumentException if the specified initial capacity
     148      *         is negative
     149      */
     150     public ArrayList(int initialCapacity) {
     151         if (initialCapacity > 0) {
     152             this.elementData = new Object[initialCapacity];
     153         } else if (initialCapacity == 0) {
     154             this.elementData = EMPTY_ELEMENTDATA;
     155         } else {
     156             throw new IllegalArgumentException("Illegal Capacity: "+
     157                                                initialCapacity);
     158         }
     159     }
     160 
     161     /**
     162      * Constructs an empty list with an initial capacity of ten.
     163      */
     164     public ArrayList() {
     165         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
     166     }
     167 
     168     /**
     169      * Constructs a list containing the elements of the specified
     170      * collection, in the order they are returned by the collection's
     171      * iterator.
     172      *
     173      * @param c the collection whose elements are to be placed into this list
     174      * @throws NullPointerException if the specified collection is null
     175      */
     176     public ArrayList(Collection<? extends E> c) {
     177         elementData = c.toArray();
     178         if ((size = elementData.length) != 0) {
     179             // c.toArray might (incorrectly) not return Object[] (see 6260652)
     180             if (elementData.getClass() != Object[].class)
     181                 elementData = Arrays.copyOf(elementData, size, Object[].class);
     182         } else {
     183             // replace with empty array.
     184             this.elementData = EMPTY_ELEMENTDATA;
     185         }
     186     }
     187 
     188     /**
     189      * Trims the capacity of this <tt>ArrayList</tt> instance to be the
     190      * list's current size.  An application can use this operation to minimize
     191      * the storage of an <tt>ArrayList</tt> instance.
     192      */
     193     public void trimToSize() {
     194         modCount++;
     195         if (size < elementData.length) {
     196             elementData = (size == 0)
     197               ? EMPTY_ELEMENTDATA
     198               : Arrays.copyOf(elementData, size);
     199         }
     200     }
     201 
     202     /**
     203      * Increases the capacity of this <tt>ArrayList</tt> instance, if
     204      * necessary, to ensure that it can hold at least the number of elements
     205      * specified by the minimum capacity argument.
     206      *
     207      * @param   minCapacity   the desired minimum capacity
     208      */
     209     public void ensureCapacity(int minCapacity) {
     210         int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
     211             // any size if not default element table
     212             ? 0
     213             // larger than default for default empty table. It's already
     214             // supposed to be at default size.
     215             : DEFAULT_CAPACITY;
     216 
     217         if (minCapacity > minExpand) {
     218             ensureExplicitCapacity(minCapacity);
     219         }
     220     }
     221 
     222     private void ensureCapacityInternal(int minCapacity) {
     223         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
     224             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
     225         }
     226 
     227         ensureExplicitCapacity(minCapacity);
     228     }
     229 
     230     private void ensureExplicitCapacity(int minCapacity) {
     231         modCount++;
     232 
     233         // overflow-conscious code
     234         if (minCapacity - elementData.length > 0)
     235             grow(minCapacity);
     236     }
     237 
     238     /**
     239      * The maximum size of array to allocate.
     240      * Some VMs reserve some header words in an array.
     241      * Attempts to allocate larger arrays may result in
     242      * OutOfMemoryError: Requested array size exceeds VM limit
     243      */
     244     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
     245 
     246     /**
     247      * Increases the capacity to ensure that it can hold at least the
     248      * number of elements specified by the minimum capacity argument.
     249      *
     250      * @param minCapacity the desired minimum capacity
     251      */
     252     private void grow(int minCapacity) {
     253         // overflow-conscious code
     254         int oldCapacity = elementData.length;
     255         int newCapacity = oldCapacity + (oldCapacity >> 1);
     256         if (newCapacity - minCapacity < 0)
     257             newCapacity = minCapacity;
     258         if (newCapacity - MAX_ARRAY_SIZE > 0)
     259             newCapacity = hugeCapacity(minCapacity);
     260         // minCapacity is usually close to size, so this is a win:
     261         elementData = Arrays.copyOf(elementData, newCapacity);
     262     }
     263 
     264     private static int hugeCapacity(int minCapacity) {
     265         if (minCapacity < 0) // overflow
     266             throw new OutOfMemoryError();
     267         return (minCapacity > MAX_ARRAY_SIZE) ?
     268             Integer.MAX_VALUE :
     269             MAX_ARRAY_SIZE;
     270     }
     271 
     272     /**
     273      * Returns the number of elements in this list.
     274      *
     275      * @return the number of elements in this list
     276      */
     277     public int size() {
     278         return size;
     279     }
     280 
     281     /**
     282      * Returns <tt>true</tt> if this list contains no elements.
     283      *
     284      * @return <tt>true</tt> if this list contains no elements
     285      */
     286     public boolean isEmpty() {
     287         return size == 0;
     288     }
     289 
     290     /**
     291      * Returns <tt>true</tt> if this list contains the specified element.
     292      * More formally, returns <tt>true</tt> if and only if this list contains
     293      * at least one element <tt>e</tt> such that
     294      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     295      *
     296      * @param o element whose presence in this list is to be tested
     297      * @return <tt>true</tt> if this list contains the specified element
     298      */
     299     public boolean contains(Object o) {
     300         return indexOf(o) >= 0;
     301     }
     302 
     303     /**
     304      * Returns the index of the first occurrence of the specified element
     305      * in this list, or -1 if this list does not contain the element.
     306      * More formally, returns the lowest index <tt>i</tt> such that
     307      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     308      * or -1 if there is no such index.
     309      */
     310     public int indexOf(Object o) {
     311         if (o == null) {
     312             for (int i = 0; i < size; i++)
     313                 if (elementData[i]==null)
     314                     return i;
     315         } else {
     316             for (int i = 0; i < size; i++)
     317                 if (o.equals(elementData[i]))
     318                     return i;
     319         }
     320         return -1;
     321     }
     322 
     323     /**
     324      * Returns the index of the last occurrence of the specified element
     325      * in this list, or -1 if this list does not contain the element.
     326      * More formally, returns the highest index <tt>i</tt> such that
     327      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     328      * or -1 if there is no such index.
     329      */
     330     public int lastIndexOf(Object o) {
     331         if (o == null) {
     332             for (int i = size-1; i >= 0; i--)
     333                 if (elementData[i]==null)
     334                     return i;
     335         } else {
     336             for (int i = size-1; i >= 0; i--)
     337                 if (o.equals(elementData[i]))
     338                     return i;
     339         }
     340         return -1;
     341     }
     342 
     343     /**
     344      * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
     345      * elements themselves are not copied.)
     346      *
     347      * @return a clone of this <tt>ArrayList</tt> instance
     348      */
     349     public Object clone() {
     350         try {
     351             ArrayList<?> v = (ArrayList<?>) super.clone();
     352             v.elementData = Arrays.copyOf(elementData, size);
     353             v.modCount = 0;
     354             return v;
     355         } catch (CloneNotSupportedException e) {
     356             // this shouldn't happen, since we are Cloneable
     357             throw new InternalError(e);
     358         }
     359     }
     360 
     361     /**
     362      * Returns an array containing all of the elements in this list
     363      * in proper sequence (from first to last element).
     364      *
     365      * <p>The returned array will be "safe" in that no references to it are
     366      * maintained by this list.  (In other words, this method must allocate
     367      * a new array).  The caller is thus free to modify the returned array.
     368      *
     369      * <p>This method acts as bridge between array-based and collection-based
     370      * APIs.
     371      *
     372      * @return an array containing all of the elements in this list in
     373      *         proper sequence
     374      */
     375     public Object[] toArray() {
     376         return Arrays.copyOf(elementData, size);
     377     }
     378 
     379     /**
     380      * Returns an array containing all of the elements in this list in proper
     381      * sequence (from first to last element); the runtime type of the returned
     382      * array is that of the specified array.  If the list fits in the
     383      * specified array, it is returned therein.  Otherwise, a new array is
     384      * allocated with the runtime type of the specified array and the size of
     385      * this list.
     386      *
     387      * <p>If the list fits in the specified array with room to spare
     388      * (i.e., the array has more elements than the list), the element in
     389      * the array immediately following the end of the collection is set to
     390      * <tt>null</tt>.  (This is useful in determining the length of the
     391      * list <i>only</i> if the caller knows that the list does not contain
     392      * any null elements.)
     393      *
     394      * @param a the array into which the elements of the list are to
     395      *          be stored, if it is big enough; otherwise, a new array of the
     396      *          same runtime type is allocated for this purpose.
     397      * @return an array containing the elements of the list
     398      * @throws ArrayStoreException if the runtime type of the specified array
     399      *         is not a supertype of the runtime type of every element in
     400      *         this list
     401      * @throws NullPointerException if the specified array is null
     402      */
     403     @SuppressWarnings("unchecked")
     404     public <T> T[] toArray(T[] a) {
     405         if (a.length < size)
     406             // Make a new array of a's runtime type, but my contents:
     407             return (T[]) Arrays.copyOf(elementData, size, a.getClass());
     408         System.arraycopy(elementData, 0, a, 0, size);
     409         if (a.length > size)
     410             a[size] = null;
     411         return a;
     412     }
     413 
     414     // Positional Access Operations
     415 
     416     @SuppressWarnings("unchecked")
     417     E elementData(int index) {
     418         return (E) elementData[index];
     419     }
     420 
     421     /**
     422      * Returns the element at the specified position in this list.
     423      *
     424      * @param  index index of the element to return
     425      * @return the element at the specified position in this list
     426      * @throws IndexOutOfBoundsException {@inheritDoc}
     427      */
     428     public E get(int index) {
     429         rangeCheck(index);
     430 
     431         return elementData(index);
     432     }
     433 
     434     /**
     435      * Replaces the element at the specified position in this list with
     436      * the specified element.
     437      *
     438      * @param index index of the element to replace
     439      * @param element element to be stored at the specified position
     440      * @return the element previously at the specified position
     441      * @throws IndexOutOfBoundsException {@inheritDoc}
     442      */
     443     public E set(int index, E element) {
     444         rangeCheck(index);
     445 
     446         E oldValue = elementData(index);
     447         elementData[index] = element;
     448         return oldValue;
     449     }
     450 
     451     /**
     452      * Appends the specified element to the end of this list.
     453      *
     454      * @param e element to be appended to this list
     455      * @return <tt>true</tt> (as specified by {@link Collection#add})
     456      */
     457     public boolean add(E e) {
     458         ensureCapacityInternal(size + 1);  // Increments modCount!!
     459         elementData[size++] = e;
     460         return true;
     461     }
     462 
     463     /**
     464      * Inserts the specified element at the specified position in this
     465      * list. Shifts the element currently at that position (if any) and
     466      * any subsequent elements to the right (adds one to their indices).
     467      *
     468      * @param index index at which the specified element is to be inserted
     469      * @param element element to be inserted
     470      * @throws IndexOutOfBoundsException {@inheritDoc}
     471      */
     472     public void add(int index, E element) {
     473         rangeCheckForAdd(index);
     474 
     475         ensureCapacityInternal(size + 1);  // Increments modCount!!
     476         System.arraycopy(elementData, index, elementData, index + 1,
     477                          size - index);
     478         elementData[index] = element;
     479         size++;
     480     }
     481 
     482     /**
     483      * Removes the element at the specified position in this list.
     484      * Shifts any subsequent elements to the left (subtracts one from their
     485      * indices).
     486      *
     487      * @param index the index of the element to be removed
     488      * @return the element that was removed from the list
     489      * @throws IndexOutOfBoundsException {@inheritDoc}
     490      */
     491     public E remove(int index) {
     492         rangeCheck(index);
     493 
     494         modCount++;
     495         E oldValue = elementData(index);
     496 
     497         int numMoved = size - index - 1;
     498         if (numMoved > 0)
     499             System.arraycopy(elementData, index+1, elementData, index,
     500                              numMoved);
     501         elementData[--size] = null; // clear to let GC do its work
     502 
     503         return oldValue;
     504     }
     505 
     506     /**
     507      * Removes the first occurrence of the specified element from this list,
     508      * if it is present.  If the list does not contain the element, it is
     509      * unchanged.  More formally, removes the element with the lowest index
     510      * <tt>i</tt> such that
     511      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
     512      * (if such an element exists).  Returns <tt>true</tt> if this list
     513      * contained the specified element (or equivalently, if this list
     514      * changed as a result of the call).
     515      *
     516      * @param o element to be removed from this list, if present
     517      * @return <tt>true</tt> if this list contained the specified element
     518      */
     519     public boolean remove(Object o) {
     520         if (o == null) {
     521             for (int index = 0; index < size; index++)
     522                 if (elementData[index] == null) {
     523                     fastRemove(index);
     524                     return true;
     525                 }
     526         } else {
     527             for (int index = 0; index < size; index++)
     528                 if (o.equals(elementData[index])) {
     529                     fastRemove(index);
     530                     return true;
     531                 }
     532         }
     533         return false;
     534     }
     535 
     536     /*
     537      * Private remove method that skips bounds checking and does not
     538      * return the value removed.
     539      */
     540     private void fastRemove(int index) {
     541         modCount++;
     542         int numMoved = size - index - 1;
     543         if (numMoved > 0)
     544             System.arraycopy(elementData, index+1, elementData, index,
     545                              numMoved);
     546         elementData[--size] = null; // clear to let GC do its work
     547     }
     548 
     549     /**
     550      * Removes all of the elements from this list.  The list will
     551      * be empty after this call returns.
     552      */
     553     public void clear() {
     554         modCount++;
     555 
     556         // clear to let GC do its work
     557         for (int i = 0; i < size; i++)
     558             elementData[i] = null;
     559 
     560         size = 0;
     561     }
     562 
     563     /**
     564      * Appends all of the elements in the specified collection to the end of
     565      * this list, in the order that they are returned by the
     566      * specified collection's Iterator.  The behavior of this operation is
     567      * undefined if the specified collection is modified while the operation
     568      * is in progress.  (This implies that the behavior of this call is
     569      * undefined if the specified collection is this list, and this
     570      * list is nonempty.)
     571      *
     572      * @param c collection containing elements to be added to this list
     573      * @return <tt>true</tt> if this list changed as a result of the call
     574      * @throws NullPointerException if the specified collection is null
     575      */
     576     public boolean addAll(Collection<? extends E> c) {
     577         Object[] a = c.toArray();
     578         int numNew = a.length;
     579         ensureCapacityInternal(size + numNew);  // Increments modCount
     580         System.arraycopy(a, 0, elementData, size, numNew);
     581         size += numNew;
     582         return numNew != 0;
     583     }
     584 
     585     /**
     586      * Inserts all of the elements in the specified collection into this
     587      * list, starting at the specified position.  Shifts the element
     588      * currently at that position (if any) and any subsequent elements to
     589      * the right (increases their indices).  The new elements will appear
     590      * in the list in the order that they are returned by the
     591      * specified collection's iterator.
     592      *
     593      * @param index index at which to insert the first element from the
     594      *              specified collection
     595      * @param c collection containing elements to be added to this list
     596      * @return <tt>true</tt> if this list changed as a result of the call
     597      * @throws IndexOutOfBoundsException {@inheritDoc}
     598      * @throws NullPointerException if the specified collection is null
     599      */
     600     public boolean addAll(int index, Collection<? extends E> c) {
     601         rangeCheckForAdd(index);
     602 
     603         Object[] a = c.toArray();
     604         int numNew = a.length;
     605         ensureCapacityInternal(size + numNew);  // Increments modCount
     606 
     607         int numMoved = size - index;
     608         if (numMoved > 0)
     609             System.arraycopy(elementData, index, elementData, index + numNew,
     610                              numMoved);
     611 
     612         System.arraycopy(a, 0, elementData, index, numNew);
     613         size += numNew;
     614         return numNew != 0;
     615     }
     616 
     617     /**
     618      * Removes from this list all of the elements whose index is between
     619      * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
     620      * Shifts any succeeding elements to the left (reduces their index).
     621      * This call shortens the list by {@code (toIndex - fromIndex)} elements.
     622      * (If {@code toIndex==fromIndex}, this operation has no effect.)
     623      *
     624      * @throws IndexOutOfBoundsException if {@code fromIndex} or
     625      *         {@code toIndex} is out of range
     626      *         ({@code fromIndex < 0 ||
     627      *          fromIndex >= size() ||
     628      *          toIndex > size() ||
     629      *          toIndex < fromIndex})
     630      */
     631     protected void removeRange(int fromIndex, int toIndex) {
     632         modCount++;
     633         int numMoved = size - toIndex;
     634         System.arraycopy(elementData, toIndex, elementData, fromIndex,
     635                          numMoved);
     636 
     637         // clear to let GC do its work
     638         int newSize = size - (toIndex-fromIndex);
     639         for (int i = newSize; i < size; i++) {
     640             elementData[i] = null;
     641         }
     642         size = newSize;
     643     }
     644 
     645     /**
     646      * Checks if the given index is in range.  If not, throws an appropriate
     647      * runtime exception.  This method does *not* check if the index is
     648      * negative: It is always used immediately prior to an array access,
     649      * which throws an ArrayIndexOutOfBoundsException if index is negative.
     650      */
     651     private void rangeCheck(int index) {
     652         if (index >= size)
     653             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
     654     }
     655 
     656     /**
     657      * A version of rangeCheck used by add and addAll.
     658      */
     659     private void rangeCheckForAdd(int index) {
     660         if (index > size || index < 0)
     661             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
     662     }
     663 
     664     /**
     665      * Constructs an IndexOutOfBoundsException detail message.
     666      * Of the many possible refactorings of the error handling code,
     667      * this "outlining" performs best with both server and client VMs.
     668      */
     669     private String outOfBoundsMsg(int index) {
     670         return "Index: "+index+", Size: "+size;
     671     }
     672 
     673     /**
     674      * Removes from this list all of its elements that are contained in the
     675      * specified collection.
     676      *
     677      * @param c collection containing elements to be removed from this list
     678      * @return {@code true} if this list changed as a result of the call
     679      * @throws ClassCastException if the class of an element of this list
     680      *         is incompatible with the specified collection
     681      * (<a href="Collection.html#optional-restrictions">optional</a>)
     682      * @throws NullPointerException if this list contains a null element and the
     683      *         specified collection does not permit null elements
     684      * (<a href="Collection.html#optional-restrictions">optional</a>),
     685      *         or if the specified collection is null
     686      * @see Collection#contains(Object)
     687      */
     688     public boolean removeAll(Collection<?> c) {
     689         Objects.requireNonNull(c);
     690         return batchRemove(c, false);
     691     }
     692 
     693     /**
     694      * Retains only the elements in this list that are contained in the
     695      * specified collection.  In other words, removes from this list all
     696      * of its elements that are not contained in the specified collection.
     697      *
     698      * @param c collection containing elements to be retained in this list
     699      * @return {@code true} if this list changed as a result of the call
     700      * @throws ClassCastException if the class of an element of this list
     701      *         is incompatible with the specified collection
     702      * (<a href="Collection.html#optional-restrictions">optional</a>)
     703      * @throws NullPointerException if this list contains a null element and the
     704      *         specified collection does not permit null elements
     705      * (<a href="Collection.html#optional-restrictions">optional</a>),
     706      *         or if the specified collection is null
     707      * @see Collection#contains(Object)
     708      */
     709     public boolean retainAll(Collection<?> c) {
     710         Objects.requireNonNull(c);
     711         return batchRemove(c, true);
     712     }
     713 
     714     private boolean batchRemove(Collection<?> c, boolean complement) {
     715         final Object[] elementData = this.elementData;
     716         int r = 0, w = 0;
     717         boolean modified = false;
     718         try {
     719             for (; r < size; r++)
     720                 if (c.contains(elementData[r]) == complement)
     721                     elementData[w++] = elementData[r];
     722         } finally {
     723             // Preserve behavioral compatibility with AbstractCollection,
     724             // even if c.contains() throws.
     725             if (r != size) {
     726                 System.arraycopy(elementData, r,
     727                                  elementData, w,
     728                                  size - r);
     729                 w += size - r;
     730             }
     731             if (w != size) {
     732                 // clear to let GC do its work
     733                 for (int i = w; i < size; i++)
     734                     elementData[i] = null;
     735                 modCount += size - w;
     736                 size = w;
     737                 modified = true;
     738             }
     739         }
     740         return modified;
     741     }
     742 
     743     /**
     744      * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     745      * is, serialize it).
     746      *
     747      * @serialData The length of the array backing the <tt>ArrayList</tt>
     748      *             instance is emitted (int), followed by all of its elements
     749      *             (each an <tt>Object</tt>) in the proper order.
     750      */
     751     private void writeObject(java.io.ObjectOutputStream s)
     752         throws java.io.IOException{
     753         // Write out element count, and any hidden stuff
     754         int expectedModCount = modCount;
     755         s.defaultWriteObject();
     756 
     757         // Write out size as capacity for behavioural compatibility with clone()
     758         s.writeInt(size);
     759 
     760         // Write out all elements in the proper order.
     761         for (int i=0; i<size; i++) {
     762             s.writeObject(elementData[i]);
     763         }
     764 
     765         if (modCount != expectedModCount) {
     766             throw new ConcurrentModificationException();
     767         }
     768     }
     769 
     770     /**
     771      * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     772      * deserialize it).
     773      */
     774     private void readObject(java.io.ObjectInputStream s)
     775         throws java.io.IOException, ClassNotFoundException {
     776         elementData = EMPTY_ELEMENTDATA;
     777 
     778         // Read in size, and any hidden stuff
     779         s.defaultReadObject();
     780 
     781         // Read in capacity
     782         s.readInt(); // ignored
     783 
     784         if (size > 0) {
     785             // be like clone(), allocate array based upon size not capacity
     786             ensureCapacityInternal(size);
     787 
     788             Object[] a = elementData;
     789             // Read in all elements in the proper order.
     790             for (int i=0; i<size; i++) {
     791                 a[i] = s.readObject();
     792             }
     793         }
     794     }
     795 
     796     /**
     797      * Returns a list iterator over the elements in this list (in proper
     798      * sequence), starting at the specified position in the list.
     799      * The specified index indicates the first element that would be
     800      * returned by an initial call to {@link ListIterator#next next}.
     801      * An initial call to {@link ListIterator#previous previous} would
     802      * return the element with the specified index minus one.
     803      *
     804      * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     805      *
     806      * @throws IndexOutOfBoundsException {@inheritDoc}
     807      */
     808     public ListIterator<E> listIterator(int index) {
     809         if (index < 0 || index > size)
     810             throw new IndexOutOfBoundsException("Index: "+index);
     811         return new ListItr(index);
     812     }
     813 
     814     /**
     815      * Returns a list iterator over the elements in this list (in proper
     816      * sequence).
     817      *
     818      * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     819      *
     820      * @see #listIterator(int)
     821      */
     822     public ListIterator<E> listIterator() {
     823         return new ListItr(0);
     824     }
     825 
     826     /**
     827      * Returns an iterator over the elements in this list in proper sequence.
     828      *
     829      * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     830      *
     831      * @return an iterator over the elements in this list in proper sequence
     832      */
     833     public Iterator<E> iterator() {
     834         return new Itr();
     835     }
     836 
     837     /**
     838      * An optimized version of AbstractList.Itr
     839      */
     840     private class Itr implements Iterator<E> {
     841         int cursor;       // index of next element to return
     842         int lastRet = -1; // index of last element returned; -1 if no such
     843         int expectedModCount = modCount;
     844 
     845         public boolean hasNext() {
     846             return cursor != size;
     847         }
     848 
     849         @SuppressWarnings("unchecked")
     850         public E next() {
     851             checkForComodification();
     852             int i = cursor;
     853             if (i >= size)
     854                 throw new NoSuchElementException();
     855             Object[] elementData = ArrayList.this.elementData;
     856             if (i >= elementData.length)
     857                 throw new ConcurrentModificationException();
     858             cursor = i + 1;
     859             return (E) elementData[lastRet = i];
     860         }
     861 
     862         public void remove() {
     863             if (lastRet < 0)
     864                 throw new IllegalStateException();
     865             checkForComodification();
     866 
     867             try {
     868                 ArrayList.this.remove(lastRet);
     869                 cursor = lastRet;
     870                 lastRet = -1;
     871                 expectedModCount = modCount;
     872             } catch (IndexOutOfBoundsException ex) {
     873                 throw new ConcurrentModificationException();
     874             }
     875         }
     876 
     877         @Override
     878         @SuppressWarnings("unchecked")
     879         public void forEachRemaining(Consumer<? super E> consumer) {
     880             Objects.requireNonNull(consumer);
     881             final int size = ArrayList.this.size;
     882             int i = cursor;
     883             if (i >= size) {
     884                 return;
     885             }
     886             final Object[] elementData = ArrayList.this.elementData;
     887             if (i >= elementData.length) {
     888                 throw new ConcurrentModificationException();
     889             }
     890             while (i != size && modCount == expectedModCount) {
     891                 consumer.accept((E) elementData[i++]);
     892             }
     893             // update once at end of iteration to reduce heap write traffic
     894             cursor = i;
     895             lastRet = i - 1;
     896             checkForComodification();
     897         }
     898 
     899         final void checkForComodification() {
     900             if (modCount != expectedModCount)
     901                 throw new ConcurrentModificationException();
     902         }
     903     }
     904 
     905     /**
     906      * An optimized version of AbstractList.ListItr
     907      */
     908     private class ListItr extends Itr implements ListIterator<E> {
     909         ListItr(int index) {
     910             super();
     911             cursor = index;
     912         }
     913 
     914         public boolean hasPrevious() {
     915             return cursor != 0;
     916         }
     917 
     918         public int nextIndex() {
     919             return cursor;
     920         }
     921 
     922         public int previousIndex() {
     923             return cursor - 1;
     924         }
     925 
     926         @SuppressWarnings("unchecked")
     927         public E previous() {
     928             checkForComodification();
     929             int i = cursor - 1;
     930             if (i < 0)
     931                 throw new NoSuchElementException();
     932             Object[] elementData = ArrayList.this.elementData;
     933             if (i >= elementData.length)
     934                 throw new ConcurrentModificationException();
     935             cursor = i;
     936             return (E) elementData[lastRet = i];
     937         }
     938 
     939         public void set(E e) {
     940             if (lastRet < 0)
     941                 throw new IllegalStateException();
     942             checkForComodification();
     943 
     944             try {
     945                 ArrayList.this.set(lastRet, e);
     946             } catch (IndexOutOfBoundsException ex) {
     947                 throw new ConcurrentModificationException();
     948             }
     949         }
     950 
     951         public void add(E e) {
     952             checkForComodification();
     953 
     954             try {
     955                 int i = cursor;
     956                 ArrayList.this.add(i, e);
     957                 cursor = i + 1;
     958                 lastRet = -1;
     959                 expectedModCount = modCount;
     960             } catch (IndexOutOfBoundsException ex) {
     961                 throw new ConcurrentModificationException();
     962             }
     963         }
     964     }
     965 
     966     /**
     967      * Returns a view of the portion of this list between the specified
     968      * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
     969      * {@code fromIndex} and {@code toIndex} are equal, the returned list is
     970      * empty.)  The returned list is backed by this list, so non-structural
     971      * changes in the returned list are reflected in this list, and vice-versa.
     972      * The returned list supports all of the optional list operations.
     973      *
     974      * <p>This method eliminates the need for explicit range operations (of
     975      * the sort that commonly exist for arrays).  Any operation that expects
     976      * a list can be used as a range operation by passing a subList view
     977      * instead of a whole list.  For example, the following idiom
     978      * removes a range of elements from a list:
     979      * <pre>
     980      *      list.subList(from, to).clear();
     981      * </pre>
     982      * Similar idioms may be constructed for {@link #indexOf(Object)} and
     983      * {@link #lastIndexOf(Object)}, and all of the algorithms in the
     984      * {@link Collections} class can be applied to a subList.
     985      *
     986      * <p>The semantics of the list returned by this method become undefined if
     987      * the backing list (i.e., this list) is <i>structurally modified</i> in
     988      * any way other than via the returned list.  (Structural modifications are
     989      * those that change the size of this list, or otherwise perturb it in such
     990      * a fashion that iterations in progress may yield incorrect results.)
     991      *
     992      * @throws IndexOutOfBoundsException {@inheritDoc}
     993      * @throws IllegalArgumentException {@inheritDoc}
     994      */
     995     public List<E> subList(int fromIndex, int toIndex) {
     996         subListRangeCheck(fromIndex, toIndex, size);
     997         return new SubList(this, 0, fromIndex, toIndex);
     998     }
     999 
    1000     static void subListRangeCheck(int fromIndex, int toIndex, int size) {
    1001         if (fromIndex < 0)
    1002             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
    1003         if (toIndex > size)
    1004             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
    1005         if (fromIndex > toIndex)
    1006             throw new IllegalArgumentException("fromIndex(" + fromIndex +
    1007                                                ") > toIndex(" + toIndex + ")");
    1008     }
    1009 
    1010     private class SubList extends AbstractList<E> implements RandomAccess {
    1011         private final AbstractList<E> parent;
    1012         private final int parentOffset;
    1013         private final int offset;
    1014         int size;
    1015 
    1016         SubList(AbstractList<E> parent,
    1017                 int offset, int fromIndex, int toIndex) {
    1018             this.parent = parent;
    1019             this.parentOffset = fromIndex;
    1020             this.offset = offset + fromIndex;
    1021             this.size = toIndex - fromIndex;
    1022             this.modCount = ArrayList.this.modCount;
    1023         }
    1024 
    1025         public E set(int index, E e) {
    1026             rangeCheck(index);
    1027             checkForComodification();
    1028             E oldValue = ArrayList.this.elementData(offset + index);
    1029             ArrayList.this.elementData[offset + index] = e;
    1030             return oldValue;
    1031         }
    1032 
    1033         public E get(int index) {
    1034             rangeCheck(index);
    1035             checkForComodification();
    1036             return ArrayList.this.elementData(offset + index);
    1037         }
    1038 
    1039         public int size() {
    1040             checkForComodification();
    1041             return this.size;
    1042         }
    1043 
    1044         public void add(int index, E e) {
    1045             rangeCheckForAdd(index);
    1046             checkForComodification();
    1047             parent.add(parentOffset + index, e);
    1048             this.modCount = parent.modCount;
    1049             this.size++;
    1050         }
    1051 
    1052         public E remove(int index) {
    1053             rangeCheck(index);
    1054             checkForComodification();
    1055             E result = parent.remove(parentOffset + index);
    1056             this.modCount = parent.modCount;
    1057             this.size--;
    1058             return result;
    1059         }
    1060 
    1061         protected void removeRange(int fromIndex, int toIndex) {
    1062             checkForComodification();
    1063             parent.removeRange(parentOffset + fromIndex,
    1064                                parentOffset + toIndex);
    1065             this.modCount = parent.modCount;
    1066             this.size -= toIndex - fromIndex;
    1067         }
    1068 
    1069         public boolean addAll(Collection<? extends E> c) {
    1070             return addAll(this.size, c);
    1071         }
    1072 
    1073         public boolean addAll(int index, Collection<? extends E> c) {
    1074             rangeCheckForAdd(index);
    1075             int cSize = c.size();
    1076             if (cSize==0)
    1077                 return false;
    1078 
    1079             checkForComodification();
    1080             parent.addAll(parentOffset + index, c);
    1081             this.modCount = parent.modCount;
    1082             this.size += cSize;
    1083             return true;
    1084         }
    1085 
    1086         public Iterator<E> iterator() {
    1087             return listIterator();
    1088         }
    1089 
    1090         public ListIterator<E> listIterator(final int index) {
    1091             checkForComodification();
    1092             rangeCheckForAdd(index);
    1093             final int offset = this.offset;
    1094 
    1095             return new ListIterator<E>() {
    1096                 int cursor = index;
    1097                 int lastRet = -1;
    1098                 int expectedModCount = ArrayList.this.modCount;
    1099 
    1100                 public boolean hasNext() {
    1101                     return cursor != SubList.this.size;
    1102                 }
    1103 
    1104                 @SuppressWarnings("unchecked")
    1105                 public E next() {
    1106                     checkForComodification();
    1107                     int i = cursor;
    1108                     if (i >= SubList.this.size)
    1109                         throw new NoSuchElementException();
    1110                     Object[] elementData = ArrayList.this.elementData;
    1111                     if (offset + i >= elementData.length)
    1112                         throw new ConcurrentModificationException();
    1113                     cursor = i + 1;
    1114                     return (E) elementData[offset + (lastRet = i)];
    1115                 }
    1116 
    1117                 public boolean hasPrevious() {
    1118                     return cursor != 0;
    1119                 }
    1120 
    1121                 @SuppressWarnings("unchecked")
    1122                 public E previous() {
    1123                     checkForComodification();
    1124                     int i = cursor - 1;
    1125                     if (i < 0)
    1126                         throw new NoSuchElementException();
    1127                     Object[] elementData = ArrayList.this.elementData;
    1128                     if (offset + i >= elementData.length)
    1129                         throw new ConcurrentModificationException();
    1130                     cursor = i;
    1131                     return (E) elementData[offset + (lastRet = i)];
    1132                 }
    1133 
    1134                 @SuppressWarnings("unchecked")
    1135                 public void forEachRemaining(Consumer<? super E> consumer) {
    1136                     Objects.requireNonNull(consumer);
    1137                     final int size = SubList.this.size;
    1138                     int i = cursor;
    1139                     if (i >= size) {
    1140                         return;
    1141                     }
    1142                     final Object[] elementData = ArrayList.this.elementData;
    1143                     if (offset + i >= elementData.length) {
    1144                         throw new ConcurrentModificationException();
    1145                     }
    1146                     while (i != size && modCount == expectedModCount) {
    1147                         consumer.accept((E) elementData[offset + (i++)]);
    1148                     }
    1149                     // update once at end of iteration to reduce heap write traffic
    1150                     lastRet = cursor = i;
    1151                     checkForComodification();
    1152                 }
    1153 
    1154                 public int nextIndex() {
    1155                     return cursor;
    1156                 }
    1157 
    1158                 public int previousIndex() {
    1159                     return cursor - 1;
    1160                 }
    1161 
    1162                 public void remove() {
    1163                     if (lastRet < 0)
    1164                         throw new IllegalStateException();
    1165                     checkForComodification();
    1166 
    1167                     try {
    1168                         SubList.this.remove(lastRet);
    1169                         cursor = lastRet;
    1170                         lastRet = -1;
    1171                         expectedModCount = ArrayList.this.modCount;
    1172                     } catch (IndexOutOfBoundsException ex) {
    1173                         throw new ConcurrentModificationException();
    1174                     }
    1175                 }
    1176 
    1177                 public void set(E e) {
    1178                     if (lastRet < 0)
    1179                         throw new IllegalStateException();
    1180                     checkForComodification();
    1181 
    1182                     try {
    1183                         ArrayList.this.set(offset + lastRet, e);
    1184                     } catch (IndexOutOfBoundsException ex) {
    1185                         throw new ConcurrentModificationException();
    1186                     }
    1187                 }
    1188 
    1189                 public void add(E e) {
    1190                     checkForComodification();
    1191 
    1192                     try {
    1193                         int i = cursor;
    1194                         SubList.this.add(i, e);
    1195                         cursor = i + 1;
    1196                         lastRet = -1;
    1197                         expectedModCount = ArrayList.this.modCount;
    1198                     } catch (IndexOutOfBoundsException ex) {
    1199                         throw new ConcurrentModificationException();
    1200                     }
    1201                 }
    1202 
    1203                 final void checkForComodification() {
    1204                     if (expectedModCount != ArrayList.this.modCount)
    1205                         throw new ConcurrentModificationException();
    1206                 }
    1207             };
    1208         }
    1209 
    1210         public List<E> subList(int fromIndex, int toIndex) {
    1211             subListRangeCheck(fromIndex, toIndex, size);
    1212             return new SubList(this, offset, fromIndex, toIndex);
    1213         }
    1214 
    1215         private void rangeCheck(int index) {
    1216             if (index < 0 || index >= this.size)
    1217                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    1218         }
    1219 
    1220         private void rangeCheckForAdd(int index) {
    1221             if (index < 0 || index > this.size)
    1222                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    1223         }
    1224 
    1225         private String outOfBoundsMsg(int index) {
    1226             return "Index: "+index+", Size: "+this.size;
    1227         }
    1228 
    1229         private void checkForComodification() {
    1230             if (ArrayList.this.modCount != this.modCount)
    1231                 throw new ConcurrentModificationException();
    1232         }
    1233 
    1234         public Spliterator<E> spliterator() {
    1235             checkForComodification();
    1236             return new ArrayListSpliterator<E>(ArrayList.this, offset,
    1237                                                offset + this.size, this.modCount);
    1238         }
    1239     }
    1240 
    1241     @Override
    1242     public void forEach(Consumer<? super E> action) {
    1243         Objects.requireNonNull(action);
    1244         final int expectedModCount = modCount;
    1245         @SuppressWarnings("unchecked")
    1246         final E[] elementData = (E[]) this.elementData;
    1247         final int size = this.size;
    1248         for (int i=0; modCount == expectedModCount && i < size; i++) {
    1249             action.accept(elementData[i]);
    1250         }
    1251         if (modCount != expectedModCount) {
    1252             throw new ConcurrentModificationException();
    1253         }
    1254     }
    1255 
    1256     /**
    1257      * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
    1258      * and <em>fail-fast</em> {@link Spliterator} over the elements in this
    1259      * list.
    1260      *
    1261      * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
    1262      * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
    1263      * Overriding implementations should document the reporting of additional
    1264      * characteristic values.
    1265      *
    1266      * @return a {@code Spliterator} over the elements in this list
    1267      * @since 1.8
    1268      */
    1269     @Override
    1270     public Spliterator<E> spliterator() {
    1271         return new ArrayListSpliterator<>(this, 0, -1, 0);
    1272     }
    1273 
    1274     /** Index-based split-by-two, lazily initialized Spliterator */
    1275     static final class ArrayListSpliterator<E> implements Spliterator<E> {
    1276 
    1277         /*
    1278          * If ArrayLists were immutable, or structurally immutable (no
    1279          * adds, removes, etc), we could implement their spliterators
    1280          * with Arrays.spliterator. Instead we detect as much
    1281          * interference during traversal as practical without
    1282          * sacrificing much performance. We rely primarily on
    1283          * modCounts. These are not guaranteed to detect concurrency
    1284          * violations, and are sometimes overly conservative about
    1285          * within-thread interference, but detect enough problems to
    1286          * be worthwhile in practice. To carry this out, we (1) lazily
    1287          * initialize fence and expectedModCount until the latest
    1288          * point that we need to commit to the state we are checking
    1289          * against; thus improving precision.  (This doesn't apply to
    1290          * SubLists, that create spliterators with current non-lazy
    1291          * values).  (2) We perform only a single
    1292          * ConcurrentModificationException check at the end of forEach
    1293          * (the most performance-sensitive method). When using forEach
    1294          * (as opposed to iterators), we can normally only detect
    1295          * interference after actions, not before. Further
    1296          * CME-triggering checks apply to all other possible
    1297          * violations of assumptions for example null or too-small
    1298          * elementData array given its size(), that could only have
    1299          * occurred due to interference.  This allows the inner loop
    1300          * of forEach to run without any further checks, and
    1301          * simplifies lambda-resolution. While this does entail a
    1302          * number of checks, note that in the common case of
    1303          * list.stream().forEach(a), no checks or other computation
    1304          * occur anywhere other than inside forEach itself.  The other
    1305          * less-often-used methods cannot take advantage of most of
    1306          * these streamlinings.
    1307          */
    1308 
    1309         private final ArrayList<E> list;
    1310         private int index; // current index, modified on advance/split
    1311         private int fence; // -1 until used; then one past last index
    1312         private int expectedModCount; // initialized when fence set
    1313 
    1314         /** Create new spliterator covering the given  range */
    1315         ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
    1316                              int expectedModCount) {
    1317             this.list = list; // OK if null unless traversed
    1318             this.index = origin;
    1319             this.fence = fence;
    1320             this.expectedModCount = expectedModCount;
    1321         }
    1322 
    1323         private int getFence() { // initialize fence to size on first use
    1324             int hi; // (a specialized variant appears in method forEach)
    1325             ArrayList<E> lst;
    1326             if ((hi = fence) < 0) {
    1327                 if ((lst = list) == null)
    1328                     hi = fence = 0;
    1329                 else {
    1330                     expectedModCount = lst.modCount;
    1331                     hi = fence = lst.size;
    1332                 }
    1333             }
    1334             return hi;
    1335         }
    1336 
    1337         public ArrayListSpliterator<E> trySplit() {
    1338             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
    1339             return (lo >= mid) ? null : // divide range in half unless too small
    1340                 new ArrayListSpliterator<E>(list, lo, index = mid,
    1341                                             expectedModCount);
    1342         }
    1343 
    1344         public boolean tryAdvance(Consumer<? super E> action) {
    1345             if (action == null)
    1346                 throw new NullPointerException();
    1347             int hi = getFence(), i = index;
    1348             if (i < hi) {
    1349                 index = i + 1;
    1350                 @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
    1351                 action.accept(e);
    1352                 if (list.modCount != expectedModCount)
    1353                     throw new ConcurrentModificationException();
    1354                 return true;
    1355             }
    1356             return false;
    1357         }
    1358 
    1359         public void forEachRemaining(Consumer<? super E> action) {
    1360             int i, hi, mc; // hoist accesses and checks from loop
    1361             ArrayList<E> lst; Object[] a;
    1362             if (action == null)
    1363                 throw new NullPointerException();
    1364             if ((lst = list) != null && (a = lst.elementData) != null) {
    1365                 if ((hi = fence) < 0) {
    1366                     mc = lst.modCount;
    1367                     hi = lst.size;
    1368                 }
    1369                 else
    1370                     mc = expectedModCount;
    1371                 if ((i = index) >= 0 && (index = hi) <= a.length) {
    1372                     for (; i < hi; ++i) {
    1373                         @SuppressWarnings("unchecked") E e = (E) a[i];
    1374                         action.accept(e);
    1375                     }
    1376                     if (lst.modCount == mc)
    1377                         return;
    1378                 }
    1379             }
    1380             throw new ConcurrentModificationException();
    1381         }
    1382 
    1383         public long estimateSize() {
    1384             return (long) (getFence() - index);
    1385         }
    1386 
    1387         public int characteristics() {
    1388             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    1389         }
    1390     }
    1391 
    1392     @Override
    1393     public boolean removeIf(Predicate<? super E> filter) {
    1394         Objects.requireNonNull(filter);
    1395         // figure out which elements are to be removed
    1396         // any exception thrown from the filter predicate at this stage
    1397         // will leave the collection unmodified
    1398         int removeCount = 0;
    1399         final BitSet removeSet = new BitSet(size);
    1400         final int expectedModCount = modCount;
    1401         final int size = this.size;
    1402         for (int i=0; modCount == expectedModCount && i < size; i++) {
    1403             @SuppressWarnings("unchecked")
    1404             final E element = (E) elementData[i];
    1405             if (filter.test(element)) {
    1406                 removeSet.set(i);
    1407                 removeCount++;
    1408             }
    1409         }
    1410         if (modCount != expectedModCount) {
    1411             throw new ConcurrentModificationException();
    1412         }
    1413 
    1414         // shift surviving elements left over the spaces left by removed elements
    1415         final boolean anyToRemove = removeCount > 0;
    1416         if (anyToRemove) {
    1417             final int newSize = size - removeCount;
    1418             for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
    1419                 i = removeSet.nextClearBit(i);
    1420                 elementData[j] = elementData[i];
    1421             }
    1422             for (int k=newSize; k < size; k++) {
    1423                 elementData[k] = null;  // Let gc do its work
    1424             }
    1425             this.size = newSize;
    1426             if (modCount != expectedModCount) {
    1427                 throw new ConcurrentModificationException();
    1428             }
    1429             modCount++;
    1430         }
    1431 
    1432         return anyToRemove;
    1433     }
    1434 
    1435     @Override
    1436     @SuppressWarnings("unchecked")
    1437     public void replaceAll(UnaryOperator<E> operator) {
    1438         Objects.requireNonNull(operator);
    1439         final int expectedModCount = modCount;
    1440         final int size = this.size;
    1441         for (int i=0; modCount == expectedModCount && i < size; i++) {
    1442             elementData[i] = operator.apply((E) elementData[i]);
    1443         }
    1444         if (modCount != expectedModCount) {
    1445             throw new ConcurrentModificationException();
    1446         }
    1447         modCount++;
    1448     }
    1449 
    1450     @Override
    1451     @SuppressWarnings("unchecked")
    1452     public void sort(Comparator<? super E> c) {
    1453         final int expectedModCount = modCount;
    1454         Arrays.sort((E[]) elementData, 0, size, c);
    1455         if (modCount != expectedModCount) {
    1456             throw new ConcurrentModificationException();
    1457         }
    1458         modCount++;
    1459     }
    1460 }
    View Code

     贴上类的结构图:

    内容太长,分2次截图。

    直接看看里面有些什么吧!

    (1)存放集合数据的数组!  

    private static final Object[] EMPTY_ELEMENTDATA = {};//用于空实例的共享空数组实例。
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//扩展数组
    transient Object[] elementData;//存放数据的原始数组

     (2)实例化集合对象

    //【1】传入集合大小,初始化集合容量,不够时自动扩展
    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】直接拿到集合实例,不固定集合大小
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    //【3】用另外一个集合来实例化当前集合
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

     分析说明一下:

      (1)如果采用【1】中方式拿到集合对象,那么当超过设置的初始容量的时候是如何扩容的呢?

    看下面这个例子:

     1 public static void main(String[] args) throws Exception {
     2         List list=new ArrayList(2);
     3         System.out.println("扩展前集合容量1:"+getCapacity(list));
     4         list.add(1);
     5         list.add(2);
     6         System.out.println("扩展前集合容量2:"+getCapacity(list));
     7         list.add(3);
     8         list.add(4);
     9         System.out.println("扩展后集合容量3:"+getCapacity(list));
    10         list.add(5);
    11         list.add(6);
    12         System.out.println("扩展后集合容量4:"+getCapacity(list));
    13         list.add(7);
    14         list.add(8);
    15         System.out.println("扩展后集合容量5:"+getCapacity(list));
    16         list.add(9);
    17         System.out.println("扩展后集合容量6:"+getCapacity(list));
    18         list.add(10);
    19         System.out.println("扩展后集合容量7:"+getCapacity(list));
    20         for(Object o:list){
    21             System.out.println(o);
    22         }
    23         System.out.println("扩展后集合容量8:"+getCapacity(list));
    24     }
    25     //反射拿到当前集合保存数据的数组的容量
    26     static int getCapacity(List<?> l) throws Exception {  
    27         Field dataField = ArrayList.class.getDeclaredField("elementData");  
    28         dataField.setAccessible(true);  
    29         return ((Object[]) dataField.get(l)).length;  
    30     }

     输出结果:

    扩展前集合容量1:2
    扩展前集合容量2:2
    扩展后集合容量3:4
    扩展后集合容量4:6
    扩展后集合容量5:9
    扩展后集合容量6:9
    扩展后集合容量7:13
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    扩展后集合容量8:13

     从结果上,可以知道,扩展容量并不是均匀扩展的(每次都递增相同的容量),而是发生着变化的,那么这种变化规则是怎么样的呢?

    继续分析一下源码中是怎么定义的:

     1 //将指定的元素追加到列表的末尾
     2 public boolean add(E e) {
     3     ensureCapacityInternal(size + 1);  // 增量模式计数!!
     4     elementData[size++] = e;
     5     return true;
     6 }
     7 //确定内部容量的方法
     8 private void ensureCapacityInternal(int minCapacity) {
     9     if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    10         minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    11     }
    12     ensureExplicitCapacity(minCapacity);
    13 }
    14 private void ensureExplicitCapacity(int minCapacity) {
    15     modCount++;
    16     //判断当前集合是否超多最大容量,即是否有容量溢出现象
    17     if (minCapacity - elementData.length > 0)
    18         grow(minCapacity);
    19 }
    20 //集合内部维护的是数组扩容
    21 private void grow(int minCapacity) {
    22     int oldCapacity = elementData.length;//拿到当前集合大小
    23     int newCapacity = oldCapacity + (oldCapacity >> 1);//计算集合新的容量大小
    24     if (newCapacity - minCapacity < 0)
    25         newCapacity = minCapacity;
    26     if (newCapacity - MAX_ARRAY_SIZE > 0)
    27         newCapacity = hugeCapacity(minCapacity);
    28     //复制旧集合数据到新的集合中(内部维护的数组扩容-产生新的数组)
    29     elementData = Arrays.copyOf(elementData, newCapacity);
    30 }

     那么在详细看以下2行代码是如何计算增加的容量的吧:

     int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1);

    简单说明一下:“>>”运算符

      >>运算规则:按二进制形式把所有的数字向右移动对应巍峨位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1.
        语法格式:
        需要移位的数字 >> 移位的次数
        例如11 >> 2,则是将数字11右移2位
        计算过程:11的二进制形式为:0000 0000 0000 0000 0000 0000 0000 1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是0000 0000 0000 0000 0000 0000 0000 0010.转换为十进制是3.数学意义:右移一位相当于除2,右移n位相当于除以2的n次方。

    举一个简答的例子:

    1 public static void main(String[] args) throws Exception {
    2         for(int i=0;i<=10;i++){
    3             System.out.println("******当前i="+i+"***********");
    4             System.out.println("递增数值:"+((i>>1)));
    5             System.out.println("递增数后值:"+(i+(i>>1)));
    6         }
    7 }

     运行结果:

    ******当前i=0***********
    递增数值:0
    递增数后值:0
    ******当前i=1***********
    递增数值:0
    递增数后值:1
    ******当前i=2***********
    递增数值:1
    递增数后值:3
    ******当前i=3***********
    递增数值:1
    递增数后值:4
    ******当前i=4***********
    递增数值:2
    递增数后值:6
    ******当前i=5***********
    递增数值:2
    递增数后值:7
    ******当前i=6***********
    递增数值:3
    递增数后值:9
    ******当前i=7***********
    递增数值:3
    递增数后值:10
    ******当前i=8***********
    递增数值:4
    递增数后值:12
    ******当前i=9***********
    递增数值:4
    递增数后值:13
    ******当前i=10***********
    递增数值:5
    递增数后值:15

     分析可以知道:每次递增的数值为:源数值的一半,且向下取整得到的数值。

    (3)如何添加数据待集合中

      ArrayList实现类中提供了2种方法,供添加数据使用:

    public boolean add(E e) {//【1】直接在集合末尾添加一个数据
        ensureCapacityInternal(size + 1);  // 判断数据是否会溢出
        elementData[size++] = e;
        return true;
    }
    public void add(int index, E element) {//【2】添加一个数据到集合的指定位置
        rangeCheckForAdd(index);//检查位置是否合法
        ensureCapacityInternal(size + 1);  // 判断数据是否会溢出
        System.arraycopy(elementData, index, elementData, index + 1,//System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制
                         size - index);
        elementData[index] = element;
        size++;
    }

     方法【1】直接在集合末尾添加一个数据,上面已经给出了分析,这里就不在赘述了,那么来看一下方法【2】是怎么处理的!

    (1)在指定位置添加一个数据,这个指定的位置,就需要检查是否合法:

     rangeCheckForAdd(index);//检查位置是否合法
     private void rangeCheckForAdd(int index) {
            if (index > size || index < 0)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

     (2)然后就是判断,如果新增了这个元素,会不会导致整个数组的数据溢出,如果会导致溢出现象,则要扩容数组。

    具体的方法上面已经给出分析:这里再放一遍代码

    private void grow(int minCapacity) {
            // overflow-conscious code
            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);
        }

     (3)此时,位置索引值合法,数组也不会溢出了,就开始要实现如何插入。

    System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);

     上面这句代码:

    System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制。其函数原型是:

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

     参数说明:

    src:源数组; srcPos:源数组要复制的起始位置;
    dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。

    注意:src and dest都必须是同类型或者可以进行转换类型的数组.
    有趣的是这个函数可以实现自己到自己复制,比如:
    int[] fun ={0,1,2,3,4,5,6};
    System.arraycopy(fun,0,fun,3,3);
    则结果为:{0,1,2,0,1,2,6};
    实现过程是这样的,先生成一个长度为length的临时数组,将fun数组中srcPos
    到srcPos+length-1之间的数据拷贝到临时数组中,再执行System.arraycopy(临时数组,0,fun,3,3).

    (4)实现了,指定位置之后(包含指定位置)的数据,向后移动的功能后,开始在指定的位置插入数据了。并且数据长度+1

     elementData[index] = element;
            size++;

     (4)如何从集合中删除一个数据

      ArrayList实现类中提供了2种方法,供删除数据使用:

    public E remove(int index) {//【1】删除指定位置的数据
        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; //置空该位置的数据
        return oldValue;
    }
     public boolean remove(Object o) {//【2】删除指定的数据
        if (o == null) {//当前要删除的数据为null
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {//遍历数组容量,拿到要删除数据的位置索引值
                    fastRemove(index);//调用删除元素的方法
                    return true;
                }
        } else {//当前要删除的数据不为null
            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
    }
    private void rangeCheck(int index) {//判断当前位置的索引值是否合法
        if (index >= size)//要删除的数据的位置不可超过数组容量,说明:如果过小的话,也会造成异常的发生
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

     总结一下;

      (1)具体如何删除集合数据,上面代码+说明已经很明显了,这里也不在赘述了。

    有意思的是:  

    private void rangeCheck(int index) {//判断当前位置的索引值是否合法
        if (index >= size)//要删除的数据的位置不可超过数组容量,说明:如果过小的话,也会造成异常的发生
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

     在删除指定位置的数据的时候,对这个位置索引值做了合法性判断。但是只做了上限判断,下限判断 没有做。

    (1)当索引值超过数组上限容量的时候,会抛出:throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

    (2)当索引值低于数组下限容量值0的时候,如何处理呢?  

    public static void main(String[] args) throws Exception {
            List alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
            alist.remove(-1);        
        }

     运行结果:

    Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.remove(AbstractList.java:161)
    at com.xfwl.test.Test4.main(Test4.java:17)

    分析说明:

      根据运行结果,发现的确会抛出异常,但是并不是在ArrayList这个实现子类中抛出的,而是在ArrayList继承的AbstractList父类中抛出的,ArrayList重写了父类的方法,虽然其中并没有抛出: java.lang.UnsupportedOperationException

    但是查看了源码,就可以知道:父类抽象类:AbstractList的remove(int index)方法中,抛出了异常。

    public E remove(int index) {
            throw new UnsupportedOperationException();
        }

     还有一种现象:就是我们删除数据的位置超过数组上限值,也抛出:java.lang.UnsupportedOperationException

    public static void main(String[] args) {
            List alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
            alist.remove(100);
        }

     运行结果:

    Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.remove(AbstractList.java:161)
    at com.xfwl.test.Test2.main(Test2.java:11)

    分析说明:

      可以看到,超过上限值,也会抛出父类方法中的异常。

     总结一下:

       首先ArrayList是子类,AbstractList是父类。

    (1)当子类中因为超过上限,而抛出:throw new IndexOutOfBoundsException(outOfBoundsMsg(index));   但是合格异常并没有被处理,会继续往上抛,就会抛到父类中去。而父类AbstractList的实现接口List和继承AbstractCollection类中都没有:

     public E remove(int index)这个方法,换句话说就是, public E remove(int index)这个方法在AbstractList这里就终止了,也就抛出了AbstractList中的这个异常。

    (2)当子类中因为地域下限时,由于没有异常捕获或者抛出处理,所以同样会到父类中捕获抛出异常。

    (5)集合中是如何把数据传递给迭代器中的链表的呢?

    分析JDK1.8的源码,可以知道:ArrayList中提供了,三个获取迭代器的方法,2个内置的具有继承关系的迭代器类。

    三个获取迭代器的方法:

     1 public ListIterator<E> listIterator(int index) {//【1】获取数组指定位置(不是索引值)之后的数组数据存放入迭代器链表中
     2     if (index < 0 || index > size)
     3         throw new IndexOutOfBoundsException("Index: "+index);
     4     return new ListItr(index);
     5 }
     6 public ListIterator<E> listIterator() {//【2】默认的方法。获取所有的数组数据放入迭代器链表中
     7     return new ListItr(0);
     8 }
     9 
    10 public Iterator<E> iterator() {//【3】默认方法。获取所有的数组数据放入迭代器链表中
    11     return new Itr();
    12 }
    13 //说明:【2】和【3】的区别是返回的类型不懂,Iterator是ListIterator的父类

     2个内置的迭代器类:

    private class Itr implements Iterator<E> {}

    Itr类内部结构图:

     1  private class Itr implements Iterator<E> {
     2         int cursor;       // index of next element to return
     3         int lastRet = -1; // index of last element returned; -1 if no such
     4         int expectedModCount = modCount;
     5 
     6         public boolean hasNext() {
     7             return cursor != size;
     8         }
     9 
    10         @SuppressWarnings("unchecked")
    11         public E next() {
    12             checkForComodification();
    13             int i = cursor;
    14             if (i >= size)
    15                 throw new NoSuchElementException();
    16             Object[] elementData = ArrayList.this.elementData;
    17             if (i >= elementData.length)
    18                 throw new ConcurrentModificationException();
    19             cursor = i + 1;
    20             return (E) elementData[lastRet = i];
    21         }
    22 
    23         public void remove() {
    24             if (lastRet < 0)
    25                 throw new IllegalStateException();
    26             checkForComodification();
    27 
    28             try {
    29                 ArrayList.this.remove(lastRet);
    30                 cursor = lastRet;
    31                 lastRet = -1;
    32                 expectedModCount = modCount;
    33             } catch (IndexOutOfBoundsException ex) {
    34                 throw new ConcurrentModificationException();
    35             }
    36         }
    37 
    38         @Override
    39         @SuppressWarnings("unchecked")
    40         public void forEachRemaining(Consumer<? super E> consumer) {
    41             Objects.requireNonNull(consumer);
    42             final int size = ArrayList.this.size;
    43             int i = cursor;
    44             if (i >= size) {
    45                 return;
    46             }
    47             final Object[] elementData = ArrayList.this.elementData;
    48             if (i >= elementData.length) {
    49                 throw new ConcurrentModificationException();
    50             }
    51             while (i != size && modCount == expectedModCount) {
    52                 consumer.accept((E) elementData[i++]);
    53             }
    54             // update once at end of iteration to reduce heap write traffic
    55             cursor = i;
    56             lastRet = i - 1;
    57             checkForComodification();
    58         }
    59 
    60         final void checkForComodification() {
    61             if (modCount != expectedModCount)
    62                 throw new ConcurrentModificationException();
    63         }
    64     }
    View Code

     private class ListItr extends Itr implements ListIterator<E> {}

    ListItr类内部结构图:

     1  private class ListItr extends Itr implements ListIterator<E> {
     2         ListItr(int index) {
     3             super();
     4             cursor = index;
     5         }
     6 
     7         public boolean hasPrevious() {
     8             return cursor != 0;
     9         }
    10 
    11         public int nextIndex() {
    12             return cursor;
    13         }
    14 
    15         public int previousIndex() {
    16             return cursor - 1;
    17         }
    18 
    19         @SuppressWarnings("unchecked")
    20         public E previous() {
    21             checkForComodification();
    22             int i = cursor - 1;
    23             if (i < 0)
    24                 throw new NoSuchElementException();
    25             Object[] elementData = ArrayList.this.elementData;
    26             if (i >= elementData.length)
    27                 throw new ConcurrentModificationException();
    28             cursor = i;
    29             return (E) elementData[lastRet = i];
    30         }
    31 
    32         public void set(E e) {
    33             if (lastRet < 0)
    34                 throw new IllegalStateException();
    35             checkForComodification();
    36 
    37             try {
    38                 ArrayList.this.set(lastRet, e);
    39             } catch (IndexOutOfBoundsException ex) {
    40                 throw new ConcurrentModificationException();
    41             }
    42         }
    43 
    44         public void add(E e) {
    45             checkForComodification();
    46 
    47             try {
    48                 int i = cursor;
    49                 ArrayList.this.add(i, e);
    50                 cursor = i + 1;
    51                 lastRet = -1;
    52                 expectedModCount = modCount;
    53             } catch (IndexOutOfBoundsException ex) {
    54                 throw new ConcurrentModificationException();
    55             }
    56         }
    57     }
    View Code

     从代码中,我们可以看到,这两种迭代器,从根本上来说都是使用实现了 Iterator接口来存储数据,定位数据,移动数据。

    关于链表的数据结构,以后会在算法章节做另做模拟、测试和分析。

    好了,此篇到此结束了!  

  • 相关阅读:
    vim编辑器和bash算术运算入门
    vim编辑器
    egrep及文本处理工具
    grep与基本正则表达式
    bash脚本编程基础及配置文件
    博客开通了
    测试用例考虑因素
    地图测试点的总结
    app测试的case点(2)
    App 99.9%稳定
  • 原文地址:https://www.cnblogs.com/newwind/p/8977149.html
Copyright © 2020-2023  润新知