ArrayList源码解读(部分)
Posted Don1911
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList源码解读(部分)相关的知识,希望对你有一定的参考价值。
前言:他山之石,可以攻玉
(1) fastRemove(int i),内部私有方法
private void fastRemove(int index) { //ArrayList内大量使用了此变量,用来验证ArrayList对象结构是否被修改 modCount++; int numMoved = size - index - 1; //index后的元素的个数 if (numMoved > 0) //0<=index<size-1的情况 System.arraycopy(elementData, index+1, elementData, index, numMoved); //ArrayList内大量使用了此方法 //size减一,且elementData[size(new)]=null方便gc回收空间 elementData[--size] = null; //【包含index为size-1时remove()的情况】 }
(2) removeAll(c)和retainAll(c)内部的调用方法相同,只有第二个参数不同
public boolean removeAll(Collection<?> c) { //删除this和c共有的元素 Objects.requireNonNull(c); return batchRemove(c, false); } public boolean retainAll(Collection<?> c) { //保留this和c共有的元素 Objects.requireNonNull(c); return batchRemove(c, true); }
private boolean batchRemove(Collection<?> c, boolean complement) { //批量删除 final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; //是否有修改 try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) //complement=true表示保留 elementData[w++] = elementData[r]; } finally { if (r != size) { //若循环中断,则将r及后面的位置的元素复制到w起始的位置 System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // w!=size 说明数组被修改了 // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; //数组大小变为被保留元素的个数 modified = true; } } return modified; }
(3) subList(int from, int to) 截取List,是通过创建内部类SubList对象实现的
public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); //界限检查 return new SubList(this, 0, fromIndex, toIndex); //0(offset)在内部类SubList没有实际意义 ① } private class SubList extends AbstractList<E> implements RandomAccess { ...... public E set(int index, E e) { rangeCheck(index); //0<index<size checkForComodification(); E oldValue = ArrayList.this.elementData(offset + index); //修改的是原ArrayList值 offset=offset(①)+fromIndex ArrayList.this.elementData[offset + index] = e; return oldValue; //返回offset+index索引处的old Value } }
(4) iterator() 遍历,通过创建内部类Itr对象实现
public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { //采用fail-fast机制 int cursor; // 指向数组的下一个元素 (cursor = 下一个元素的索引) int lastRet = -1; // 上次返回的元素的索引; 如果不存在上次的返回值,则为-1 int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { //下一个元素 checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; //再次指向下一个元素 return (E) elementData[lastRet = i]; //将lastRet指向返回的元素 } public void remove() { //删除上次next()方法返回的元素 if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; //将被删除元素的索引赋给cursor lastRet = -1; //next()返回的元素已不存在(被删),则lastRet=-1 expectedModCount = modCount; //遍历过程中删除元素不会发生CME异常的原因! } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void forEachRemaining(Consumer<? super E> consumer) { ... } ...... }
(5) listIterator(int i) 与 listIterator(),遍历集合,通过创建内部类ListItr (extends Itr)对象实现,与Itr对比,主要增加了previous()、set()、add()方法
public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) //index=size不报错(可从后往前遍历) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } public ListIterator<E> listIterator() { return new ListItr(0); } private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { //是否存在前一个元素 return cursor != 0; } ......public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; //指向下一个元素的cursor也对应向前移动 return (E) elementData[lastRet = i]; //lastRet指向返回的元素 } public void set(E e) { //改变元素的值,相当于arrayList.set(lastRet,e); if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); //modCount不会改变 } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; //重新赋值给expectedModCount } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }
(6) spliterator() 可分割迭代器,是Java为了并行遍历数据源中的元素而设计的 通过创建内部类ArrayListSpliterator对象实现
public Spliterator<E> spliterator() { return new ArrayListSpliterator<>(this, 0, -1, 0); } /* 基于索引分割,懒初始化 */ static final class ArrayListSpliterator<E> implements Spliterator<E> { private final ArrayList<E> list; private int index; // 当前元素索引, 调用advance/split时定义其初始值 private int fence; // 使用前为-1; 调用时为size值 private int expectedModCount; // initialized when fence set ArrayListSpliterator(ArrayList<E> list, int origin, int fence, //new ArrayListSpliterator<>(this, 0, -1, 0); int expectedModCount) { this.list = list; // 不遍历时list可为null this.index = origin; //起始索引 this.fence = fence; //边界 this.expectedModCount = expectedModCount; } private int getFence() { // 首次使用时将fence初始化为size值 int hi; // 一个出现在forEach()中特殊的变量 ArrayList<E> lst; if ((hi = fence) < 0) { if ((lst = list) == null) hi = fence = 0; else { expectedModCount = lst.modCount; hi = fence = lst.size; } } return hi; } public ArrayListSpliterator<E> trySplit() { //分割 int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid) ? null : // 除非元素太少(0或1),否则从中间(mid)分割 new ArrayListSpliterator<E>(list, lo, index = mid, //父spliterator的index变为mid expectedModCount); //即分割后,父spliterator[mid,size-1] //子spliterator[index, mid-1] } public boolean tryAdvance(Consumer<? super E> action) { //对index索引处的元素进行操作 if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; //② if (i < hi) { //若spliterator元素不为空 index = i + 1; //index索引+1 @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; action.accept(e); //对index(②)处的元素进行操作,可能改变原数组的元素 if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); return true; } return false; } public void forEachRemaining(Consumer<? super E> action) { int i, hi, mc; // hoist accesses and checks from loop ArrayList<E> lst; Object[] a; if (action == null) throw new NullPointerException(); if ((lst = list) != null && (a = lst.elementData) != null) { if ((hi = fence) < 0) { //若fence未初始化,即未曾调用trySplite()或tryAdvance(Consumer c) mc = lst.modCount; hi = lst.size; } else mc = expectedModCount; if ((i = index) >= 0 && (index = hi) <= a.length) { for (; i < hi; ++i) { @SuppressWarnings("unchecked") E e = (E) a[i]; action.accept(e); //操作index至hence-1的元素 } if (lst.modCount == mc) return; } } throw new ConcurrentModificationException(); } public long estimateSize() { //返回listerator大小 return (long) (getFence() - index); } public int characteristics() { //返回特征值(不同值相或后的结果不相等,所以可通过该值辨识出有什么特征) return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; } }
其它方法相对上面方法易懂
以上是关于ArrayList源码解读(部分)的主要内容,如果未能解决你的问题,请参考以下文章