/** * The array buffer into which the elements of the ArrayList are stored * The capacity of the ArrayList is the length of this array buffer. */ privatetransient Object[] elementData;
/** * The size of the ArrayList (the number of elements it contains). * @serial */ privateint size;
/** * Constructs an empty list with the specified initial capacity. */ publicArrayList(int initialCapacity) { if (initialCapacity > 0) { //初始容量大于0,实例化数组 this.elementData = newObject[initialCapacity]; } elseif (initialCapacity == 0) { //初始容量为0 this.elementData = EMPTY_ELEMENTDATA; //空数组 } else { thrownewIllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } /** ArrayList无参构造函数。 * Constructs an empty list with an initial capacity of ten. */ publicArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** 创建一个包含collection的ArrayList * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. */ publicArrayList(Collection<? extends E> c) { elementData = c.toArray(); //先转化成数组 if ((size = elementData.length) != 0) { //如果集合不为空 // c.toArray might (incorrectly) not return Object[] if (elementData.getClass() != Object[].class) //给elementData 赋值 elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 如果是一个空的集合,用空数组来替换 this.elementData = EMPTY_ELEMENTDATA; } }
有参的两个构造器很好理解,下面说下无参的构造器。 EMPTY_ELEMENTDATA是什么的?看名字就知道了,是一个空的数组。DEFAULTCAPACITY_EMPTY_ELEMENTDATA也是一个空数组。那么他们之间有什么区别呢?为什么ArrayList无参构造函数构造的是一个DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空数组呢?因为以前的代码是直接初始化一个长度为10的数组。看上面的注释,我们可以知道,We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first element is added.就是当第一个元素被加入到elementData中时,区分这两者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/** * 默认的初始容量为10 */ privatestaticfinalintDEFAULT_CAPACITY=10; /** * Shared empty array instance used for empty instances. */ privatestaticfinal Object[] EMPTY_ELEMENTDATA = {}; /** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first element is added. */ privatestaticfinal Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
1./** 2. * Increases the capacity of this <tt>ArrayList</tt> instance, if 3. * necessary, to ensure that it can hold at least the number of elements 4. * specified by the minimum capacity argument. 5. * 6. * @param minCapacity the desired minimum capacity 7. */ 8.publicvoidensureCapacity(int minCapacity) { 9.intminExpand= (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 10.// any size if not default element table 11. ? 0 12.// larger than default for default empty table. It's already 13.// supposed to be at default size. 14. : DEFAULT_CAPACITY; 15. 16.if (minCapacity > minExpand) { 17. ensureExplicitCapacity(minCapacity); 18. } 19. } 20. 21.privatevoidensureCapacityInternal(int minCapacity) { 22.if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 23. minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 24. } 25. ensureExplicitCapacity(minCapacity); 26. } 27. 28.privatevoidensureExplicitCapacity(int minCapacity) { 29. modCount++; 30.if (minCapacity - elementData.length > 0) 31. grow(minCapacity); 32. }
1./** 容量扩充,确保数组中至少能包含minimum capacity个元素 2. * Increases the capacity to ensure that it can hold at least the 3. * number of elements specified by the minimum capacity argument. 4. * 5. * @param minCapacity the desired minimum capacity 6. */ 7.privatevoidgrow(int minCapacity) { 8.intoldCapacity= elementData.length; 9.intnewCapacity= oldCapacity + (oldCapacity >> 1); //原来容量的1.5倍 10.if (newCapacity - minCapacity < 0) 11. newCapacity = minCapacity; 12.if (newCapacity - MAX_ARRAY_SIZE > 0) 13. newCapacity = hugeCapacity(minCapacity); 14.// minCapacity is usually close to size, so this is a win: 15. elementData = Arrays.copyOf(elementData, newCapacity); 16. } 17.//对大容量数组的处理 18.privatestaticinthugeCapacity(int minCapacity) { 19.if (minCapacity < 0) // overflow 20.thrownewOutOfMemoryError(); 21.return (minCapacity > MAX_ARRAY_SIZE) ? 22. Integer.MAX_VALUE : 23. MAX_ARRAY_SIZE; 24. }
// 返回此列表中指定位置上的元素。 public E get(int index) { RangeCheck(index); return (E) elementData[index]; }
元素删除:
ArrayList提供了根据下标或者指定对象两种方式的删除功能。如下:
romove(int index):
1 2 3 4 5 6 7 8 9 10 11 12
// 移除此列表中指定位置上的元素。 public E remove(int index) { RangeCheck(index); modCount++; EoldValue= (E) elementData[index]; intnumMoved= size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; }
// 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。 publicbooleanremove(Object o) { // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。 if (o == null) { for (intindex=0; index < size; index++) if (elementData[index] == null) { // 类似remove(int index),移除列表中指定位置上的元素。 fastRemove(index); returntrue; } } else { for (intindex=0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); returntrue; } } returnfalse; } }
首先通过代码可以看到,当移除成功后返回true,否则返回false。remove(Object o)中通过遍历element寻找是否存在传入对象,一旦找到就调用fastRemove移除对象。为什么找到了元素就知道了index,不通过remove(index)来移除元素呢?因为fastRemove跳过了判断边界的处理,因为找到元素就相当于确定了index不会超过边界,而且fastRemove并不返回被移除的元素。下面是fastRemove的代码,基本和remove(index)一致。方法说明:skips bounds checking and does notreturn the value removed.
1 2 3 4 5 6 7
privatevoidfastRemove(int index) { modCount++; intnumMoved= size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work }
1.//保留集合c中的元素,集合外的元素全部删除 2. Retains only the elements in this list that are contained in the 3. * specified collection. In other words, removes from this list all 4. * of its elements that are not contained in the specified collection. 5.publicbooleanretainAll(Collection<?> c) { 6. Objects.requireNonNull(c); 7.return batchRemove(c, true); 8. } 9. 10.privatebooleanbatchRemove(Collection<?> c, boolean complement) { 11.final Object[] elementData = this.elementData; 12.intr=0, w = 0; 13.booleanmodified=false; 14.try { 15.for (; r < size; r++) 16.if (c.contains(elementData[r]) == complement) 17. elementData[w++] = elementData[r]; 18. } finally { 19.// Preserve behavioral compatibility with AbstractCollection, 20.// even if c.contains() throws. 21.if (r != size) { 22. System.arraycopy(elementData, r, 23. elementData, w, 24. size - r); 25. w += size - r; 26. } 27.if (w != size) { 28.// clear to let GC do its work 29.for (inti= w; i < size; i++) 30. elementData[i] = null; 31. modCount += size - w; 32. size = w; 33. modified = true; 34. } 35. } 36.return modified; 37. }
removeRange(int fromIndex,int toIndex)
1 2 3 4 5 6 7 8 9 10 11
protectedvoidremoveRange(int fromIndex, int toIndex) { modCount++; intnumMoved= size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work intnewSize= size - (toIndex-fromIndex); while (size != newSize) elementData[--size] = null; }
执行过程是将elementData从toIndex位置开始的元素向前移动到fromIndex,然后将toIndex位置之后的元素全部置空顺便修改size。 这个方法是protected,及受保护的方法,为什么这个方法被定义为protected呢? 这是一个解释,但是可能不容易看明白。http://stackoverflow.com/questions/2289183/why-is-javas-abstractlists-removerange-method-protected 先看下面这个例子 1. ArrayList ints = new ArrayList(Arrays.asList(0, 1, 2, 2. 3, 4, 5, 6)); 3. // fromIndex low endpoint (inclusive) of the subList 4. // toIndex high endpoint (exclusive) of the subList 5. ints.subList(2, 4).clear(); 6. System.out.println(ints); 输出结果是[0, 1, 4, 5, 6],结果是不是像调用了removeRange(int fromIndex,int toIndex)!哈哈哈,就是这样的。但是为什么效果相同呢?是不是调用了removeRange(int fromIndex,int toIndex)呢?
public <T> T[] toArray(T[] 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()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
publicintindexOf(Object o) { if (o == null) { for (inti=0; i < size; i++) if (elementData[i]==null) return i; } else { for (inti=0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
publicintlastIndexOf(Object o) { if (o == null) { for (inti= size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (inti= size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }
/** * Save the state of the <tt>ArrayList</tt> instance to a stream (that * is, serialize it). 把arraylist实例写入一个流中 */ privatevoidwriteObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff intexpectedModCount= modCount; s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { thrownewConcurrentModificationException(); } } /** * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, * deserialize it). 从流中读出一个ArrayList实例 */ privatevoidreadObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff s.defaultReadObject();
// Read in capacity s.readInt(); // ignored if (size > 0) { // be like clone(), allocate array based upon size not capacity ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }