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

一、JDK中ArrayList是如何实现的

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

《Java基础-集合框架-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>中定义了那些规则?

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

JDK1.8中的源码 

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

  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中的源码:

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

  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

 

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

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

 说明一下:

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

  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中的源码:

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

  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

 

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

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

说明一下:

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

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

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

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

 

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

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

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

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

   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

 贴上类的结构图:

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

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

内容太长,分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类内部结构图:

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

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

 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类内部结构图:

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

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

 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接口来存储数据,定位数据,移动数据。

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

好了,此篇到此结束了!  

    原文作者:小风微灵-彦
    原文地址: https://www.cnblogs.com/newwind/p/8977149.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞