源码分析——ArrayList的add,get,retainAll方法原理分析
Posted 喵喵7781
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码分析——ArrayList的add,get,retainAll方法原理分析相关的知识,希望对你有一定的参考价值。
ArrayList的add方法
/**
* 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.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = ;
/**
* Default initial capacity. 默认初始化容量为10.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
*
* <p>This field is used by the iterator and list iterator implementation
* returned by the @code iterator and @code listIterator methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a @code ConcurrentModificationException in
* response to the @code next, @code remove, @code previous,
* @code set or @code add operations. This provides
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
* <p><b>Use of this field by subclasses is optional.</b> If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its @code add(int, E) and
* @code remove(int) methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* @code add(int, E) or @code remove(int) must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus @code ConcurrentModificationExceptions. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored. modCount值是用于fail-fast检验的。
*/
protected transient int modCount = 0;
/**
* 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
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by @link Collection#add)
*/
public boolean add(E e)
//1.判断数组是否需要扩容,不够就扩容,够就放弃
ensureCapacityInternal(size + 1); // Increments modCount!!
//2.值放到之前数组最后一个值的后面
elementData[size++] = e;
//3.返回成功
return true;
private void ensureCapacityInternal(int minCapacity)
//1.当前数组跟初始化数组相等,默认容量和add的容量对比,选出最大值为当前容量。
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
//2.计算精确容量
ensureExplicitCapacity(minCapacity);
private void ensureExplicitCapacity(int minCapacity)
//1.modCount值加1
modCount++;
//2.如果当前容量>内存中数组现有容量,扩容
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
/**
* 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
*/
private void grow(int minCapacity)
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果计算扩容后新容量小于原始容量,则新容量=旧容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果计算后的容量超过了integer最大值,则最大容量为Integer的最大值
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//采用Arrays.copyof方法进行扩容
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
private static int hugeCapacity(int minCapacity)
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
总结一下:
1.判断是否需要扩容
1)初始化:初始化的时候,默认容量为10,对10进行数组创建。
2)第二次扩容:当添加第11数据的时候,新容量=10+10>>1=15,在采用Arrays.copyOf进行扩容。……
2.给扩容后的数组,赋值到原始数据的最后一位。
3.返回true
ArrayList的get方法
/**
* 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)
//1.判断数组是否下标越界
rangeCheck(index);
//2.直接返回值
return elementData(index);
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void rangeCheck(int index)
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
E elementData(int index)
return (E) elementData[index];
总结一下:
1.判断数组是否下标越界,抛出运行时异常IndexOutOfBoundsException,非受检异常。
2.直接返回数组的值。
ArrayList的retainAll方法
/**
* Retains only the elements in this list that are contained in the
* specified collection. In other words, removes from this list all
* of its elements that are not contained in the specified collection.
*
* @param c collection containing elements to be retained in this list
* @return @code true if this list changed as a result of the call
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list contains a null element and the
* specified collection does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see Collection#contains(Object)
*/
public boolean retainAll(Collection<?> c)
//判断集合是否为空
Objects.requireNonNull(c);
//取集合交集
return batchRemove(c, true);
/**
* Checks that the specified object reference is not @code null. This
* method is designed primarily for doing parameter validation in methods
* and constructors, as demonstrated below:
* <blockquote><pre>
* public Foo(Bar bar)
* this.bar = Objects.requireNonNull(bar);
*
* </pre></blockquote>
*
* @param obj the object reference to check for nullity
* @param <T> the type of the reference
* @return @code obj if not @code null
* @throws NullPointerException if @code obj is @code null
*/
public static <T> T requireNonNull(T obj)
if (obj == null)
throw new NullPointerException();
return obj;
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)
elementData[w++] = elementData[r];
finally
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size)
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
if (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;
/**
* Copies an array from the specified source array, beginning at the
* specified position, to the specified position of the destination array.
* A subsequence of array components are copied from the source
* array referenced by <code>src</code> to the destination array
* referenced by <code>dest</code>. The number of components copied is
* equal to the <code>length</code> argument. The components at
* positions <code>srcPos</code> through
* <code>srcPos+length-1</code> in the source array are copied into
* positions <code>destPos</code> through
* <code>destPos+length-1</code>, respectively, of the destination
* array.
* <p>
* If the <code>src</code> and <code>dest</code> arguments refer to the
* same array object, then the copying is performed as if the
* components at positions <code>srcPos</code> through
* <code>srcPos+length-1</code> were first copied to a temporary
* array with <code>length</code> components and then the contents of
* the temporary array were copied into positions
* <code>destPos</code> through <code>destPos+length-1</code> of the
* destination array.
* <p>
* If <code>dest</code> is <code>null</code>, then a
* <code>NullPointerException</code> is thrown.
* <p>
* If <code>src</code> is <code>null</code>, then a
* <code>NullPointerException</code> is thrown and the destination
* array is not modified.
* <p>
* Otherwise, if any of the following is true, an
* <code>ArrayStoreException</code> is thrown and the destination is
* not modified:
* <ul>
* <li>The <code>src</code> argument refers to an object that is not an
* array.
* <li>The <code>dest</code> argument refers to an object that is not an
* array.
* <li>The <code>src</code> argument and <code>dest</code> argument refer
* to arrays whose component types are different primitive types.
* <li>The <code>src</code> argument refers to an array with a primitive
* component type and the <code>dest</code> argument refers to an array
* with a reference component type.
* <li>The <code>src</code> argument refers to an array with a reference
* component type and the <code>dest</code> argument refers to an array
* with a primitive component type.
* </ul>
* <p>
* Otherwise, if any of the following is true, an
* <code>IndexOutOfBoundsException</code> is
* thrown and the destination is not modified:
* <ul>
* <li>The <code>srcPos</code> argument is negative.
* <li>The <code>destPos</code> argument is negative.
* <li>The <code>length</code> argument is negative.
* <li><code>srcPos+length</code> is greater than
* <code>src.length</code>, the length of the source array.
* <li><code>destPos+length</code> is greater than
* <code>dest.length</code>, the length of the destination array.
* </ul>
* <p>
* Otherwise, if any actual component of the source array from
* position <code>srcPos</code> through
* <code>srcPos+length-1</code> cannot be converted to the component
* type of the destination array by assignment conversion, an
* <code>ArrayStoreException</code> is thrown. In this case, let
* <b><i>k</i></b> be the smallest nonnegative integer less than
* length such that <code>src[srcPos+</code><i>k</i><code>]</code>
* cannot be converted to the component type of the destination
* array; when the exception is thrown, source array components from
* positions <code>srcPos</code> through
* <code>srcPos+</code><i>k</i><code>-1</code>
* will already have been copied to destination array positions
* <code>destPos</code> through
* <code>destPos+</code><i>k</I><code>-1</code> and no other
* positions of the destination array will have been modified.
* (Because of the restrictions already itemized, this
* paragraph effectively applies only to the situation where both
* arrays have component types that are reference types.)
*
* @param src the source array.
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
* @exception IndexOutOfBoundsException if copying would cause
* access of data outside array bounds.
* @exception ArrayStoreException if an element in the <code>src</code>
* array could not be stored into the <code>dest</code> array
* because of a type mismatch.
* @exception NullPointerException if either <code>src</code> or
* <code>dest</code> is <code>null</code>.
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
总结一下:
1.判断集合是否为空
2.正常情况:遍历当前集合,如果给定集合包含当前集合中的元素,则放到当前数组里面。最后清空不等位置的值。取交集。
异常情况:把集合剩下的没有来得及进行比较的元素直接copy到原集合。(不是很懂----------)
以上是关于源码分析——ArrayList的add,get,retainAll方法原理分析的主要内容,如果未能解决你的问题,请参考以下文章