java集合ArrayList

基于jdk_1.8.0

关于List,主要是有序的可重复的数据结构。jdk主要实现类有ArrayList(底层使用数组)、LinkedList(底层使用双向链表)
  ArrayList:

  (一)继承关系图

    

  (二)源码解析

    (1)关键字段   

 1 /**
 2      * 默认初始容量
 3      */
 4     private static final int DEFAULT_CAPACITY = 10;
 5 
 6     /**
 7      * 用于空实例的共享空数组实例
 8      */
 9     private static final Object[] EMPTY_ELEMENTDATA = {};
10 
11     /**
12      * 用于默认大小的空实例的共享空数组实例
13      */
14     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
15 
16     /**
17      *存储ArrayList元素的数组缓冲区
18      */
19     transient Object[] elementData; //非私有以简化嵌套类访问
20 
21     /**
22      * ArrayList的大小,也是下一个元素插入的位置
23      */
24     private int size;
25 
26     /**
27      * 要分配的数组的最大大小 
28      * 从hugeCapacity方法可以看到如果要分配的大小 > MAX_ARRAY_SIZE ,会返回Integer.MAX_VALUE
29      */
30     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;    // 关于-8 ,网上说是数组元数据信息要占8个字节  字节和大小有哪门子关系,这个不够让人信服
View Code

    (2)构造方法    

 1 /**
 2      * elementData指向共享的默认空数组实例,将在添加第一个元素时扩展到DEFAULT_CAPACITY
 3      */
 4     public ArrayList() {
 5         //默认的空数组实例,主要是为了区别 new ArrayList(0)
 6         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 7     }
 8 
 9     /**
10      * 构造一个initialCapacity大小的数组
11      */
12     public ArrayList(int initialCapacity) {
13         if (initialCapacity > 0) {
14             this.elementData = new Object[initialCapacity];
15         } else if (initialCapacity == 0) {
16             //空数组实例
17             this.elementData = EMPTY_ELEMENTDATA;
18         } else {
19             throw new IllegalArgumentException("Illegal Capacity: "+
20                     initialCapacity);
21         }
22     }
23 
24     /**
25      * 构造一个包含指定集合的元素的列表,这些元素按集合的迭代器返回的顺序排列
26      */
27     public ArrayList(Collection<? extends E> c) {
28         //详见toArray实例方法
29         elementData = c.toArray();
30         //集合不为空
31         if ((size = elementData.length) != 0) {
32             //虽然elementData 是object[]类型的,但是它指向的类型不一定是Object[]
33             //造成的原因可能是Arrays.asList详情请戳https://www.cnblogs.com/liqing-weikeyuan/p/7922306.html
34             if (elementData.getClass() != Object[].class)
35                 elementData = Arrays.copyOf(elementData, size, Object[].class);
36         } else {
37             this.elementData = EMPTY_ELEMENTDATA;
38         }
39     }
View Code

    (3)常用方法

      a. public boolean add(E e)     

 1 public boolean add(E e) {
 2         // 为了确保数组不越界,所以允许的数组最小容量为size + 1
 3         ensureCapacityInternal(size + 1);  // Increments modCount!!
 4         elementData[size++] = e;
 5         return true;
 6     }
 7 
 8     private void ensureCapacityInternal(int minCapacity) {
 9         // 由于calculateCapacity是静态方法,无法访问实例elementData变量
10         ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
11     }
12 
13     /**
14      * 为啥要设计成静态方法,想不通
15      */
16     private static int calculateCapacity(Object[] elementData, int minCapacity) {
17         // 若是通过默认构造方法构造,则返回DEFAULT_CAPACITY
18         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
19             return Math.max(DEFAULT_CAPACITY, minCapacity);
20         }
21         return minCapacity;
22     }
23 
24     private void ensureExplicitCapacity(int minCapacity) {
25         modCount++;
26 
27         // overflow-conscious code
28         // 若数组不足以放下,则进行扩充
29         if (minCapacity - elementData.length > 0)
30             grow(minCapacity);
31     }
32 
33     /**
34      * 新的数组容量先按之前的1.5倍进行扩充
35      * 若扩充后的大小还不足以放下,则使用minCapacity
36      * 若minCapacity > MAX_ARRAY_SIZE,最大容量Integer.MAX_VALUE,否则内存溢出异常
37      * @param minCapacity
38      */
39     private void grow(int minCapacity) {
40         // overflow-conscious code
41         int oldCapacity = elementData.length;
42         int newCapacity = oldCapacity + (oldCapacity >> 1);
43         if (newCapacity - minCapacity < 0)
44             newCapacity = minCapacity;
45         if (newCapacity - MAX_ARRAY_SIZE > 0)
46             newCapacity = hugeCapacity(minCapacity);
47         // minCapacity is usually close to size, so this is a win:
48         elementData = Arrays.copyOf(elementData, newCapacity);
49     }
50 
51     private static int hugeCapacity(int minCapacity) {
52         // 容量超过Integer.MAX_VALUE
53         if (minCapacity < 0) // overflow
54             throw new OutOfMemoryError();
55         return (minCapacity > MAX_ARRAY_SIZE) ?
56                 Integer.MAX_VALUE :
57                 MAX_ARRAY_SIZE;
58     }
View Code

      b.  public void add(int index, E element)

 1 /**
 2      * 向指定位置添加元素,不常用,性能也不好
 3      * @param index
 4      * @param element
 5      */
 6     public void add(int index, E element) {
 7         rangeCheckForAdd(index);
 8 
 9         ensureCapacityInternal(size + 1);  // Increments modCount!!
10         // [index, size -1] 向后移动一位
11         System.arraycopy(elementData, index, elementData, index + 1,
12                 size - index);
13         elementData[index] = element;
14         size++;
15     }
16 
17     /**
18      * A version of rangeCheck used by add and addAll.
19      */
20     private void rangeCheckForAdd(int index) {
21         if (index > size || index < 0)
22             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
23     }
24 
25     /**
26      * 详见 a. public boolean add(E e) 不再展开
27      * @param minCapacity
28      */
29     private void ensureCapacityInternal(int minCapacity) {
30         ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
31     }
View Code

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

 

1 public boolean addAll(Collection<? extends E> c) {
2         Object[] a = c.toArray();
3         int numNew = a.length;
4         ensureCapacityInternal(size + numNew);  // 详见a. add
5         System.arraycopy(a, 0, elementData, size, numNew);
6         size += numNew;
7         return numNew != 0;   //??? 暂时没看懂
8     }
View Code

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

  

 1  /**
 2      * 向指定位置添加集合元素
 3      * @param index
 4      * @param c
 5      * @return
 6      */
 7     public boolean addAll(int index, Collection<? extends E> c) {
 8         rangeCheckForAdd(index);
 9 
10         Object[] a = c.toArray();
11         int numNew = a.length;
12         ensureCapacityInternal(size + numNew);  // Increments modCount
13 
14         // 需要移动元素个数
15         int numMoved = size - index;
16         if (numMoved > 0)
17             System.arraycopy(elementData, index, elementData, index + numNew,
18                     numMoved);  //从index开始复制numMoved个元素到index + numNew (即[index, index + numMoved -1] 复制到[index + numNew, index + numNew + numMoved - 1])
19 
20         System.arraycopy(a, 0, elementData, index, numNew);
21         size += numNew;
22         return numNew != 0; //??? 没看懂
23     }
View Code

       e. public E remove(int index)

 1 /**
 2      * 删除指定位置的元素
 3      * @param index
 4      * @return 被删除的元素
 5      * @throws java.lang.ArrayIndexOutOfBoundsException
 6      */
 7     public E remove(int index) {
 8         rangeCheck(index);
 9 
10         modCount++;
11         E oldValue = elementData(index);
12 
13         int numMoved = size - index - 1;
14         if (numMoved > 0)
15             System.arraycopy(elementData, index+1, elementData, index,
16                     numMoved); //把[index + 1, size -1]元素 复制到 [index, size -2]
17         elementData[--size] = null; // clear to let GC do its work
18 
19         return oldValue;
20     }
21 
22     private void rangeCheck(int index) {
23         if (index >= size)
24             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
25     }
26 
27     private String outOfBoundsMsg(int index) {
28         return "Index: "+index+", Size: "+size;
29     }
30 
31     /**
32      * @throws java.lang.ArrayIndexOutOfBoundsException
33      */
34     E elementData(int index) {
35         return (E) elementData[index];
36     }
View Code

      f. public boolean remove(Object o)

 1 /**
 2      * 删除第一个值为o的元素
 3      * @param o
 4      * @return
 5      */
 6     public boolean remove(Object o) {
 7         if (o == null) {
 8             for (int index = 0; index < size; index++)
 9                 if (elementData[index] == null) {
10                     fastRemove(index);
11                     return true;
12                 }
13         } else {
14             for (int index = 0; index < size; index++)
15                 if (o.equals(elementData[index])) {
16                     fastRemove(index);
17                     return true;
18                 }
19         }
20         return false;
21     }
22 
23     private void fastRemove(int index) {
24         modCount++;
25         int numMoved = size - index - 1;
26         if (numMoved > 0)
27             System.arraycopy(elementData, index+1, elementData, index,
28                     numMoved);
29         elementData[--size] = null; // clear to let GC do its work
30     }
View Code

      g. public boolean removeAll(Collection<?> c)

 1 public boolean removeAll(Collection<?> c) {
 2         Objects.requireNonNull(c);
 3         return batchRemove(c, false);
 4     }
 5 
 6     // Objects.class
 7     public static <T> T requireNonNull(T obj) {
 8         if (obj == null)
 9             throw new NullPointerException();
10         return obj;
11     }
12 
13     private boolean batchRemove(Collection<?> c, boolean complement) {
14         final Object[] elementData = this.elementData;
15         int r = 0, w = 0;
16         boolean modified = false;
17         try {
18             for (; r < size; r++)
19                 if (c.contains(elementData[r]) == complement)
20                     elementData[w++] = elementData[r]; // 把没有包含的统一移动到数组的一端
21         } finally {
22             // Preserve behavioral compatibility with AbstractCollection,
23             // even if c.contains() throws.
24             if (r != size) {
25                 // 前r个元素已经过滤完毕,这里只是简单的把[r, size-1]的元素复制移动到[w, w + size -r -1]
26                 System.arraycopy(elementData, r,
27                         elementData, w,
28                         size - r);
29                 w += size - r;
30             }
31             if (w != size) {
32                 // clear to let GC do its work
33                 for (int i = w; i < size; i++)
34                     elementData[i] = null;
35                 modCount += size - w;
36                 size = w;
37                 modified = true;
38             }
39         }
40         return modified;
41     }
View Code

      h. public E set(int index, E element)

1 public E set(int index, E element) {
2         rangeCheck(index);
3 
4         E oldValue = elementData(index);    //强制转换成E
5         elementData[index] = element;
6         return oldValue;
7     }
View Code

      i. public E get(int index)

1 public E get(int index) {
2         rangeCheck(index);
3 
4         return elementData(index);  // 强制转化成E
5     }
View Code

      j. public int indexOf(Object o)

 1 /**
 2      * 获取指定元素的下标
 3      * @param o
 4      * @return 
 5      */
 6     public int indexOf(Object o) {
 7         if (o == null) {
 8             for (int i = 0; i < size; i++)
 9                 if (elementData[i]==null)
10                     return i;
11         } else {
12             for (int i = 0; i < size; i++)
13                 if (o.equals(elementData[i]))
14                     return i;
15         }
16         return -1;
17     }
View Code

      k. public int lastIndexOf(Object o)

 1 public int lastIndexOf(Object o) {
 2         if (o == null) {
 3             for (int i = size-1; i >= 0; i--)
 4                 if (elementData[i]==null)
 5                     return i;
 6         } else {
 7             for (int i = size-1; i >= 0; i--)
 8                 if (o.equals(elementData[i]))
 9                     return i;
10         }
11         return -1;
12     }
View Code

      l. public Iterator<E> iterator()

 1 public Iterator<E> iterator() {
 2         return new Itr();
 3     }
 4 
 5     /**
 6      * An optimized version of AbstractList.Itr
 7      */
 8     private class Itr implements Iterator<E> {
 9         int cursor;       // index of next element to return
10         int lastRet = -1; // index of last element returned; -1 if no such
11         int expectedModCount = modCount;
12 
13         Itr() {}
14 
15         public boolean hasNext() {
16             return cursor != size;
17         }
18 
19         @SuppressWarnings("unchecked")
20         public E next() {
21             checkForComodification();
22             int i = cursor;
23             if (i >= size)  //数组内实际存储的元素个数
24                 throw new NoSuchElementException();
25             Object[] elementData = ArrayList.this.elementData;
26             if (i >= elementData.length)
27                 throw new ConcurrentModificationException();
28             cursor = i + 1;
29             return (E) elementData[lastRet = i];
30         }
31 
32         public void remove() {
33             if (lastRet < 0)    //没有首先调用next(), 直接remove会抛IllegalStateException
34                 throw new IllegalStateException();
35             checkForComodification();
36 
37             try {
38                 ArrayList.this.remove(lastRet);   //详见e. public E remove(int index)
39                 cursor = lastRet;
40                 lastRet = -1;
41                 expectedModCount = modCount;
42             } catch (IndexOutOfBoundsException ex) {    //该异常什么情况下会被触发???
43                 throw new ConcurrentModificationException();
44             }
45         }
46 
47         @Override
48         @SuppressWarnings("unchecked")
49         public void forEachRemaining(Consumer<? super E> consumer) {
50             Objects.requireNonNull(consumer);
51             final int size = ArrayList.this.size;
52             int i = cursor;
53             if (i >= size) {
54                 return;
55             }
56             final Object[] elementData = ArrayList.this.elementData;
57             if (i >= elementData.length) {
58                 throw new ConcurrentModificationException();
59             }
60             while (i != size && modCount == expectedModCount) {
61                 consumer.accept((E) elementData[i++]);
62             }
63             // update once at end of iteration to reduce heap write traffic
64             cursor = i;
65             lastRet = i - 1;
66             checkForComodification();
67         }
68 
69         final void checkForComodification() {
70             if (modCount != expectedModCount)
71                 throw new ConcurrentModificationException();
72         }
73     }
View Code

      m. public ListIterator<E> listIterator()

 1 public ListIterator<E> listIterator() {
 2         return new ListItr(0);
 3     }
 4 
 5     /**
 6      * An optimized version of AbstractList.ListItr
 7      */
 8     private class ListItr extends Itr implements ListIterator<E> {
 9         // 初始化游标位置,默认0
10         ListItr(int index) {
11             super();
12             cursor = index;
13         }
14 
15         // 只有第一个元素没有前继节点
16         public boolean hasPrevious() {
17             return cursor != 0;
18         }
19 
20         public int nextIndex() {
21             return cursor;
22         }
23 
24         public int previousIndex() {
25             return cursor - 1;
26         }
27 
28         @SuppressWarnings("unchecked")
29         public E previous() {
30             checkForComodification();
31             int i = cursor - 1;
32             if (i < 0)
33                 throw new NoSuchElementException();
34             Object[] elementData = ArrayList.this.elementData;
35             if (i >= elementData.length)
36                 throw new ConcurrentModificationException();
37             cursor = i;
38             return (E) elementData[lastRet = i];
39         }
40 
41         public void set(E e) {
42             if (lastRet < 0)
43                 throw new IllegalStateException();
44             checkForComodification();
45 
46             try {
47                 ArrayList.this.set(lastRet, e);     // 详见 h. public E set(int index, E element)
48             } catch (IndexOutOfBoundsException ex) {
49                 throw new ConcurrentModificationException();
50             }
51         }
52 
53         /**
54          * 由于底层调用的是add(int index, E element), 还要有一次数组拷贝,性能不如 add(E element)
55          * @param e
56          */
57         public void add(E e) {
58             checkForComodification();
59 
60             try {
61                 int i = cursor;
62                 ArrayList.this.add(i, e);     //详见b.  public void add(int index, E element)
63                 cursor = i + 1;
64                 lastRet = -1;
65                 expectedModCount = modCount;
66             } catch (IndexOutOfBoundsException ex) {
67                 throw new ConcurrentModificationException();
68             }
69         }
70     }
View Code

      n. public ListIterator<E> listIterator(int index)

 1 /**
 2      * 指定游标
 3      * @param index
 4      * @return
 5      */
 6     public ListIterator<E> listIterator(int index) {
 7         if (index < 0 || index > size)
 8             throw new IndexOutOfBoundsException("Index: "+index);
 9         return new ListItr(index);  // 详情请看 j. public ListIterator<E> listIterator()
10     }
View Code

      o. public void forEach(Consumer<? super E> action)

 1 @Override
 2     public void forEach(Consumer<? super E> action) {
 3         Objects.requireNonNull(action);
 4         final int expectedModCount = modCount;
 5         @SuppressWarnings("unchecked")
 6         final E[] elementData = (E[]) this.elementData;
 7         final int size = this.size;
 8         for (int i=0; modCount == expectedModCount && i < size; i++) {
 9             action.accept(elementData[i]);  //使用见下面解析
10         }
11         if (modCount != expectedModCount) {
12             throw new ConcurrentModificationException();
13         }
14     }
15 
16     // Consumer.class
17     @FunctionalInterface    // 使用该注解就表明可以使用lambda,只要接口只有一个抽象方法就可以用lambda
18     public interface Consumer<T> {
19 
20         void accept(T t);
21 
22         /**
23          * 可以看到andThen方法返回的是一个Consumer匿名类对象c
24          * 程序运行中如果不调用c.accept(),则什么也不会发生
25          * @param after
26          * @return
27          */
28         default Consumer<T> andThen(Consumer<? super T> after) {
29             Objects.requireNonNull(after);
30             return (T t) -> { accept(t); after.accept(t); };    //重写了accept方法
31         }
32     }
33 
34     // TestConsumer.class
35     public void testAccept(String[] args) {
36         // jdk8 之前写法
37         Consumer<String> c = new Consumer<String>() {
38             @Override
39             public void accept(String s) {
40                 System.out.println(s.toLowerCase());
41             }
42         };
43 
44         // jdk8 lambda写法
45         Consumer<String> c = (s) -> System.out.println(s.toLowerCase());
46         c.accept("HELLO world!");   // hello world!
47     }
48 
49     public void testAndthen(String[] args) {
50         /**
51          * 通过这个例子可以看出首先调用了a.accept(),然后调用了b.accept()
52          */
53         Consumer<String> a = (x) -> System.out.print(x.toLowerCase());
54         Consumer<String> b = (x) -> {
55             System.out.println("...andThen..." + x);
56         };
57         Consumer<String> c = a.andThen(b);
58         c.accept("HELLO world!");  // hello world!...andThen...HELLO world!
59     }
View Code

      p. public void sort(Comparator<? super E> c)   //TODO 先不展开

 1 @Override
 2     @SuppressWarnings("unchecked")
 3     public void sort(Comparator<? super E> c) {
 4         final int expectedModCount = modCount;
 5         Arrays.sort((E[]) elementData, 0, size, c);
 6         if (modCount != expectedModCount) {
 7             throw new ConcurrentModificationException();
 8         }
 9         modCount++;
10     }
View Code

      q. public List<E> subList(int fromIndex, int toIndex)

  1 /**
  2      * 注意,该subList并没有new一个新的object[], 对subList对象的修改,都会作用到原大对象上
  3      */
  4     public List<E> subList(int fromIndex, int toIndex) {
  5         subListRangeCheck(fromIndex, toIndex, size);
  6         return new SubList(this, 0, fromIndex, toIndex);
  7     }
  8 
  9     static void subListRangeCheck(int fromIndex, int toIndex, int size) {
 10         if (fromIndex < 0)
 11             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
 12         if (toIndex > size)
 13             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
 14         if (fromIndex > toIndex)
 15             throw new IllegalArgumentException("fromIndex(" + fromIndex +
 16                     ") > toIndex(" + toIndex + ")");
 17     }
 18 
 19     /**
 20      * subList 并没有再new一个object[],而是复用
 21      */
 22     private class SubList extends AbstractList<E> implements RandomAccess {
 23         private final AbstractList<E> parent;
 24         private final int parentOffset;
 25         private final int offset;
 26         int size;
 27 
 28         SubList(AbstractList<E> parent,
 29                 int offset, int fromIndex, int toIndex) {
 30             this.parent = parent;
 31             this.parentOffset = fromIndex;
 32             this.offset = offset + fromIndex;
 33             this.size = toIndex - fromIndex;
 34             this.modCount = ArrayList.this.modCount;
 35         }
 36 
 37         public E set(int index, E e) {
 38             rangeCheck(index);
 39             checkForComodification();
 40             E oldValue = ArrayList.this.elementData(offset + index);
 41             ArrayList.this.elementData[offset + index] = e;
 42             return oldValue;
 43         }
 44 
 45         public E get(int index) {
 46             rangeCheck(index);
 47             checkForComodification();
 48             return ArrayList.this.elementData(offset + index);
 49         }
 50 
 51         public int size() {
 52             checkForComodification();
 53             return this.size;
 54         }
 55 
 56         public void add(int index, E e) {
 57             rangeCheckForAdd(index);
 58             checkForComodification();
 59             parent.add(parentOffset + index, e);
 60             this.modCount = parent.modCount;
 61             this.size++;
 62         }
 63 
 64         public E remove(int index) {
 65             rangeCheck(index);
 66             checkForComodification();
 67             E result = parent.remove(parentOffset + index);
 68             this.modCount = parent.modCount;
 69             this.size--;
 70             return result;
 71         }
 72 
 73         protected void removeRange(int fromIndex, int toIndex) {
 74             checkForComodification();
 75             parent.removeRange(parentOffset + fromIndex,
 76                     parentOffset + toIndex);
 77             this.modCount = parent.modCount;
 78             this.size -= toIndex - fromIndex;
 79         }
 80 
 81         public boolean addAll(Collection<? extends E> c) {
 82             return addAll(this.size, c);
 83         }
 84 
 85         public boolean addAll(int index, Collection<? extends E> c) {
 86             rangeCheckForAdd(index);
 87             int cSize = c.size();
 88             if (cSize==0)
 89                 return false;
 90 
 91             checkForComodification();
 92             parent.addAll(parentOffset + index, c);
 93             this.modCount = parent.modCount;
 94             this.size += cSize;
 95             return true;
 96         }
 97 
 98         public Iterator<E> iterator() {
 99             return listIterator();
100         }
101 
102         public ListIterator<E> listIterator(final int index) {
103             checkForComodification();
104             rangeCheckForAdd(index);
105             final int offset = this.offset;
106 
107             return new ListIterator<E>() {
108                 int cursor = index;
109                 int lastRet = -1;
110                 int expectedModCount = ArrayList.this.modCount;
111 
112                 public boolean hasNext() {
113                     return cursor != SubList.this.size;
114                 }
115 
116                 @SuppressWarnings("unchecked")
117                 public E next() {
118                     checkForComodification();
119                     int i = cursor;
120                     if (i >= SubList.this.size)
121                         throw new NoSuchElementException();
122                     Object[] elementData = ArrayList.this.elementData;
123                     if (offset + i >= elementData.length)
124                         throw new ConcurrentModificationException();
125                     cursor = i + 1;
126                     return (E) elementData[offset + (lastRet = i)];
127                 }
128 
129                 public boolean hasPrevious() {
130                     return cursor != 0;
131                 }
132 
133                 @SuppressWarnings("unchecked")
134                 public E previous() {
135                     checkForComodification();
136                     int i = cursor - 1;
137                     if (i < 0)
138                         throw new NoSuchElementException();
139                     Object[] elementData = ArrayList.this.elementData;
140                     if (offset + i >= elementData.length)
141                         throw new ConcurrentModificationException();
142                     cursor = i;
143                     return (E) elementData[offset + (lastRet = i)];
144                 }
145 
146                 @SuppressWarnings("unchecked")
147                 public void forEachRemaining(Consumer<? super E> consumer) {
148                     Objects.requireNonNull(consumer);
149                     final int size = SubList.this.size;
150                     int i = cursor;
151                     if (i >= size) {
152                         return;
153                     }
154                     final Object[] elementData = ArrayList.this.elementData;
155                     if (offset + i >= elementData.length) {
156                         throw new ConcurrentModificationException();
157                     }
158                     while (i != size && modCount == expectedModCount) {
159                         consumer.accept((E) elementData[offset + (i++)]);
160                     }
161                     // update once at end of iteration to reduce heap write traffic
162                     lastRet = cursor = i;
163                     checkForComodification();
164                 }
165 
166                 public int nextIndex() {
167                     return cursor;
168                 }
169 
170                 public int previousIndex() {
171                     return cursor - 1;
172                 }
173 
174                 public void remove() {
175                     if (lastRet < 0)
176                         throw new IllegalStateException();
177                     checkForComodification();
178 
179                     try {
180                         SubList.this.remove(lastRet);
181                         cursor = lastRet;
182                         lastRet = -1;
183                         expectedModCount = ArrayList.this.modCount;
184                     } catch (IndexOutOfBoundsException ex) {
185                         throw new ConcurrentModificationException();
186                     }
187                 }
188 
189                 public void set(E e) {
190                     if (lastRet < 0)
191                         throw new IllegalStateException();
192                     checkForComodification();
193 
194                     try {
195                         ArrayList.this.set(offset + lastRet, e);
196                     } catch (IndexOutOfBoundsException ex) {
197                         throw new ConcurrentModificationException();
198                     }
199                 }
200 
201                 public void add(E e) {
202                     checkForComodification();
203 
204                     try {
205                         int i = cursor;
206                         SubList.this.add(i, e);
207                         cursor = i + 1;
208                         lastRet = -1;
209                         expectedModCount = ArrayList.this.modCount;
210                     } catch (IndexOutOfBoundsException ex) {
211                         throw new ConcurrentModificationException();
212                     }
213                 }
214 
215                 final void checkForComodification() {
216                     if (expectedModCount != ArrayList.this.modCount)
217                         throw new ConcurrentModificationException();
218                 }
219             };
220         }
221 
222         public List<E> subList(int fromIndex, int toIndex) {
223             subListRangeCheck(fromIndex, toIndex, size);
224             return new SubList(this, offset, fromIndex, toIndex);
225         }
226 
227         private void rangeCheck(int index) {
228             if (index < 0 || index >= this.size)
229                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
230         }
231 
232         private void rangeCheckForAdd(int index) {
233             if (index < 0 || index > this.size)
234                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
235         }
236 
237         private String outOfBoundsMsg(int index) {
238             return "Index: "+index+", Size: "+this.size;
239         }
240 
241         private void checkForComodification() {
242             if (ArrayList.this.modCount != this.modCount)
243                 throw new ConcurrentModificationException();
244         }
245 
246         public Spliterator<E> spliterator() {
247             checkForComodification();
248             return new ArrayListSpliterator<E>(ArrayList.this, offset,
249                     offset + this.size, this.modCount);
250         }
251     }
View Code

      r. public <T> T[] toArray(T[] a)

 1 /**
 2      * 推荐使用 toArray(T[] a)
 3      */
 4     public Object[] toArray() {
 5         return Arrays.copyOf(elementData, size);
 6     }
 7 
 8     /**
 9      * 如果a.length不足以放下所有的元素,则新建一个size大小的数组拷贝返回
10      * 如果a.length足够放下,遍历的时候小心空指针
11      * 推荐a.length == size new T[list.size()]
12      */
13     public <T> T[] toArray(T[] a) {
14         if (a.length < size)    // 传过来的数组大小不足以放下全部元素
15             // Make a new array of a's runtime type, but my contents:
16             return (T[]) Arrays.copyOf(elementData, size, a.getClass());
17         System.arraycopy(elementData, 0, a, 0, size);
18         if (a.length > size)
19             a[size] = null;     // ???没懂用意
20         return a;
21     }
View Code

      s. 其它简单方法

 1 /**
 2      * 返回当前列表元素个数
 3      * @return
 4      */
 5     public int size() {
 6         return size;
 7     }
 8 
 9     /**
10      * 当前列表是否为空
11      * @return
12      */
13     public boolean isEmpty() {
14         return size == 0;
15     }
16 
17     /**
18      * 当前列表是否包含元素o
19      * @return
20      */
21     public boolean contains(Object o) {
22         return indexOf(o) >= 0;     //详情请看 j. public int indexOf(Object o)
23     }
24 
25     /**
26      * 将elementData中未使用的空间 释放掉
27      */
28     public void trimToSize() {
29         modCount++;
30         if (size < elementData.length) {
31             elementData = (size == 0)
32                     ? EMPTY_ELEMENTDATA
33                     : Arrays.copyOf(elementData, size);
34         }
35     }
36 
37     /**
38      * 清空所有引用
39      */
40     public void clear() {
41         modCount++;
42 
43         // clear to let GC do its work
44         for (int i = 0; i < size; i++)
45             elementData[i] = null;
46 
47         size = 0;
48     }
View Code

      t. 序列化相关方法

 1 private void readObject(java.io.ObjectInputStream s)
 2             throws java.io.IOException, ClassNotFoundException {
 3         elementData = EMPTY_ELEMENTDATA;
 4 
 5         // Read in size, and any hidden stuff
 6         s.defaultReadObject();
 7 
 8         // Read in capacity
 9         s.readInt(); // ignored
10 
11         if (size > 0) {
12             // be like clone(), allocate array based upon size not capacity
13             int capacity = calculateCapacity(elementData, size);
14             SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
15             ensureCapacityInternal(size);
16 
17             Object[] a = elementData;
18             // Read in all elements in the proper order.
19             for (int i=0; i<size; i++) {
20                 a[i] = s.readObject();
21             }
22         }
23     }
24 
25     private void writeObject(java.io.ObjectOutputStream s)
26             throws java.io.IOException{
27         // Write out element count, and any hidden stuff
28         int expectedModCount = modCount;
29         s.defaultWriteObject();
30 
31         // Write out size as capacity for behavioural compatibility with clone()
32         s.writeInt(size);
33 
34         // Write out all elements in the proper order.
35         for (int i=0; i<size; i++) {
36             s.writeObject(elementData[i]);
37         }
38 
39         if (modCount != expectedModCount) {
40             throw new ConcurrentModificationException();
41         }
42     }
View Code

 

写在最后:

  使用ArrayList进行存储的元素,务必要重写Object的equals方法。像IndexOf、lastIndexOf、remove等方法底层都是调用元素的equals方法进行比较;

  通过get、set方法可以看出,ArrayList随机读写指定位置的元素速度非常快,但是remove、add等方法可能还需要有移动操作,故速度较慢;

  通过remove indexOf 等方法可以看出ArrayList可以存储null值;

  ArrayList.size 区间范围[0, Integer.MAX_VALUE], 超过Integer.MAX_VALUE,抛OutOfMemoryError。实际应用中还需要具体调整JVM内存大小;

  通过代码可以看出,ArrayList任何方法均没有锁,故ArrayList是非线程安全的,若要在多线程环境下使用,要么调用者在外部同步要么参考Collections.synchronizedList(new ArrayList());

  ListIterator增强了Iterator一些功能,添加了add、set、hasPrevious、previousIndex、previous、nextIndex方法,调用remove方法时,务必首先调用next或者previous;

  subList 应该注意,对subList对象的任何修改都会作用到原对象上;

  toArray,返回的是一个全新的对象,对其修改不会影响原list对象。
  

Q1:for-each与iterator使用场景
A1:如果一个集合或者数组需要更新元素(修改|删除),那么需要使用iterator或者普通for循环;

  如果对于集合List使用iterator,建议优先选择使用listIterator;

  如果只遍历集合元素,建议优先使用forEach或者支持并行的stream(jdk8以上),否则使用for-each。

posted @ 2018-12-04 17:07  呆小田  阅读(208)  评论(0编辑  收藏  举报