/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access
/** * The size of the ArrayList (the number of elements it contains). * * @serial */ privateint size;
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ publicArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = newObject[initialCapacity]; } elseif (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { thrownewIllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
/** * Constructs an empty list with an initial capacity of ten. */ publicArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
/** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ publicArrayList(Collection<? extends E> c) { Object[] a = c.toArray(); if ((size = a.length) != 0) { if (c.getClass() == ArrayList.class) { elementData = a; } else { elementData = Arrays.copyOf(a, size, Object[].class); } } else { // replace with empty array. elementData = EMPTY_ELEMENTDATA; } }
/** * Increases the capacity of this {@code ArrayList} instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ publicvoidensureCapacity(int minCapacity) { if (minCapacity > elementData.length && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA && minCapacity <= DEFAULT_CAPACITY)) { modCount++; grow(minCapacity); } }
/** * The maximum size of array to allocate (unless necessary). * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ privatestaticfinalintMAX_ARRAY_SIZE= Integer.MAX_VALUE - 8;
/** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity * @throws OutOfMemoryError if minCapacity is less than zero */ private Object[] grow(int minCapacity) { returnelementData= Arrays.copyOf(elementData, newCapacity(minCapacity)); }
/** * Returns a capacity at least as large as the given minimum capacity. * Returns the current capacity increased by 50% if that suffices. * Will not return a capacity greater than MAX_ARRAY_SIZE unless * the given minimum capacity is greater than MAX_ARRAY_SIZE. * * @param minCapacity the desired minimum capacity * @throws OutOfMemoryError if minCapacity is less than zero */ privateintnewCapacity(int minCapacity) { // overflow-conscious code intoldCapacity= elementData.length; intnewCapacity= oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity <= 0) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) return Math.max(DEFAULT_CAPACITY, minCapacity); if (minCapacity < 0) // overflow thrownewOutOfMemoryError(); return minCapacity; } return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity : hugeCapacity(minCapacity); }
/** * This helper method split out from add(E) to keep method * bytecode size under 35 (the -XX:MaxInlineSize default value), * which helps when add(E) is called in a C1-compiled loop. */ privatevoidadd(E e, Object[] elementData, int s) { // 转为inline method,执行更快 if (s == elementData.length) elementData = grow(); elementData[s] = e; size = s + 1; }
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ publicbooleanadd(E e) { modCount++; add(e, elementData, size); returntrue; }
/** * Inserts the specified element at the specified position in this * list. Shifts the element currently at that position (if any) and * any subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ publicvoidadd(int index, E element) { rangeCheckForAdd(index); modCount++; finalint s; Object[] elementData; if ((s = size) == (elementData = this.elementData).length) elementData = grow(); System.arraycopy(elementData, index, elementData, index + 1, s - index); elementData[index] = element; size = s + 1; }
/** * A version of rangeCheck used by add and addAll. */ privatevoidrangeCheckForAdd(int index) { if (index > size || index < 0) thrownewIndexOutOfBoundsException(outOfBoundsMsg(index)); }
publicbooleanaddAll(Collection<? extends E> c) { Object[] a = c.toArray(); modCount++; intnumNew= a.length; if (numNew == 0) returnfalse; Object[] elementData; finalint s; if (numNew > (elementData = this.elementData).length - (s = size)) elementData = grow(s + numNew); System.arraycopy(a, 0, elementData, s, numNew); size = s + numNew; returntrue; }
publicbooleanaddAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index);
Object[] a = c.toArray(); modCount++; intnumNew= a.length; if (numNew == 0) returnfalse; Object[] elementData; finalint s; if (numNew > (elementData = this.elementData).length - (s = size)) elementData = grow(s + numNew);
intnumMoved= s - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size = s + numNew; returntrue; }
set()
先检查下标范围,之后直接对指定位置赋值
1 2 3 4 5 6
public E set(int index, E element) { Objects.checkIndex(index, size); EoldValue= elementData(index); elementData[index] = element; return oldValue; }
get()
先检查下标范围,获取对应位置的元素后,进行类型转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
E elementData(int index) { return (E) elementData[index]; }
static <E> E elementAt(Object[] es, int index) { return (E) es[index]; }
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { Objects.checkIndex(index, size); return elementData(index); }
public E remove(int index) { Objects.checkIndex(index, size); final Object[] es = elementData;
EoldValue= (E) es[index]; fastRemove(es, index);
return oldValue; }
publicbooleanremove(Object o) { final Object[] es = elementData; finalintsize=this.size; inti=0; found: { if (o == null) { for (; i < size; i++) if (es[i] == null) break found; } else { for (; i < size; i++) if (o.equals(es[i])) break found; } returnfalse; } fastRemove(es, i); returntrue; }
privatevoidfastRemove(Object[] es, int i) { modCount++; finalint newSize; if ((newSize = size - 1) > i) System.arraycopy(es, i + 1, es, i, newSize - i); es[size = newSize] = null; // 清除该位置的引用 }
intindexOfRange(Object o, int start, int end) { Object[] es = elementData; if (o == null) { for (inti= start; i < end; i++) { if (es[i] == null) { return i; } } } else { for (inti= start; i < end; i++) { if (o.equals(es[i])) { return i; } } } return -1; }
intlastIndexOfRange(Object o, int start, int end) { Object[] es = elementData; if (o == null) { for (inti= end - 1; i >= start; i--) { if (es[i] == null) { return i; } } } else { for (inti= end - 1; i >= start; i--) { if (o.equals(es[i])) { return i; } } } return -1; }
privateclassItrimplementsIterator<E> { int cursor; // index of next element to return intlastRet= -1; // index of last element returned; -1 if no such intexpectedModCount= modCount;
// prevent creating a synthetic constructor Itr() {}
publicbooleanhasNext() { return cursor != size; }
public E next() { checkForComodification(); inti= cursor; if (i >= size) thrownewNoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) thrownewConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }
publicvoidremove() { if (lastRet < 0) thrownewIllegalStateException(); checkForComodification();