//数组扩容后,新的数组大小。新增原数组的一半 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); }
//移除首次出现的元素o。实现逻辑为:首先在数组中找到元素o首次出现的索引index, // 找到索引后,调用fastRemove()方法,移除index处的元素。实现逻辑与remove(int index)方法部分相似。都是将数组elementData的index位置之后的元素依次往前移动 publicbooleanremove(Object o){ if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); returntrue; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); returntrue; } } returnfalse; }
//与remove(int index)方法不同之处:跳过了范围检查,并且不用返回删除的元素 privatevoidfastRemove(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 }
removeRange源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//移除数组中[fromIndex, toIndex) 范围内的元素 protectedvoidremoveRange(int fromIndex, int toIndex){ modCount++;
//待往前移动的元素个数。其中包含索引toIndex处的元素 int numMoved = size - toIndex;
// clear to let GC do its work //清除移除的元素 int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; }
// 通过底层将数组中的元素拷贝到新数组中,然后返回 public Object[] toArray() { return Arrays.copyOf(elementData, size); }
public <T> T[] toArray(T[] a) { //在数组a的长度小于目前数组的大小时,直接通过底层拷贝一份,类型为a的类型 if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//如果参数a的容量足够容下所有元素,则直接通过System.arraycopy进行复制 System.arraycopy(elementData, 0, a, 0, size);
//将数组中的多余位置置为null if (a.length > size) a[size] = null;
//返回参数 o 在数组中首次出现的索引 publicintindexOf(Object o){ /** * 整体逻辑: * 如果参数o为null,则遍历数组,如果有null值,则返回首次出现的位置; * 如果参数o不为null。则遍历数组,如果有与参数o相同的元素,则返回首次出现的位置; */ if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
//返回参数 o 在数组中最后出现的索引。与indexOf()方法不同之处为:lastIndexOf()方法是从数组尾部开始遍历;而ndexOf()方法是从数组头部开始遍历 publicintlastIndexOf(Object o){ if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }
这两个方法都是查找元素o在列表中国首次出现或者最后出现的索引
clone源码
1 2 3 4 5 6 7 8 9 10 11 12
//浅拷贝 public Object clone(){ try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable thrownew InternalError(e); } }
/** * An optimized version of AbstractList.Itr */ privateclassItrimplementsIterator<E> { //下一个返回元素的索引 int cursor; // index of next element to return //返回最后一个元素的索引 int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;
@SuppressWarnings("unchecked") public E next(){ //校验。ArrayList常见的坑是:使用forEach循环遍历数组中,有删除操作时,会报ConcurrentModificationException错误 checkForComodification(); int i = cursor;
//如果超过了数组大小,则抛NoSuchElementException异常 if (i >= size) thrownew NoSuchElementException(); Object[] elementData = ArrayList.this.elementData;
//如果超过了数组元素数,则抛ConcurrentModificationException异常 if (i >= elementData.length) thrownew ConcurrentModificationException();
@Override @SuppressWarnings("unchecked") publicvoidforEachRemaining(Consumer<? super E> consumer){ Objects.requireNonNull(consumer); finalint size = ArrayList.this.size; int i = cursor; if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) { thrownew ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]); } // update once at end of iteration to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); }
finalvoidcheckForComodification(){ if (modCount != expectedModCount) thrownew ConcurrentModificationException(); } }
/** * An optimized version of AbstractList.ListItr */ privateclassListItrextendsItrimplementsListIterator<E> { ListItr(int index) { super(); cursor = index; }
@SuppressWarnings("unchecked") public E previous(){ checkForComodification(); int i = cursor - 1; if (i < 0) thrownew NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) thrownew ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; }
publicvoidset(E e){ if (lastRet < 0) thrownew IllegalStateException(); checkForComodification();