码迷,mamicode.com
首页 > 其他好文 > 详细

ArrayList

时间:2017-12-11 00:55:19      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:分享图片   size   源码   地方法   []   flow   margin   provides   view   

ArrayList是java集合框架中List体系下List接口的一个实现类。

特点:

Resizable(大小可调,尺寸可变)-array (Resizable-array implementation of the <tt>List</tt> interface.This class provides methods to manipulate(巧妙处理) the size of the                   array that is used internally to store the list.)

  所以ArrayList拥有数组元素有序的特点。

  As elements are added to an ArrayList,its capacity grows automatically.  The details of the growth policy are not specified beyond the fact that adding an element has             constant amortized time cost.

Including null (Implements all optional list operations, and permits all elements, including <tt>null</tt>.)

Note that this implementation is not synchronized.

  If multiple threads access an <tt>ArrayList</tt> instance concurrently, and at least one of the threads modifies the list structurally, it <i>must</i> be synchronized externally.

  If no such object exists, the list should be "wrapped" using the {@link Collections#synchronizedList Collections.synchronizedList} method. This is best done at creation time,   to prevent accidental unsynchronized access to the list:

  <pre> List list = Collections.synchronizedList(new ArrayList(...));</pre>

方法的时间复杂度

The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,<tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant  time(时间复杂度O(1)).

The <tt>add</tt> operation runs in <i>amortized constant time</i>, that is, adding n elements requires O(n) time(时间复杂度 O(n)).

迭代器(fail-fast)

if the list is structurally modified at any time after the iterator is created, in any way except through the iterator‘s own {@link ListIterator#remove() remove} or
{@link ListIterator#add(Object) add} methods, the iterator will throw a
{@link ConcurrentModificationException}.

Thus, in the face of  concurrent modification, the iterator fails quickly and cleanly, rather  than risking arbitrary, non-deterministic behavior at an undetermined  time in the future.

 

如何保证动态扩容

  这里主要分析一下,ArrayList#add方法。再说add方法之前,我想说一下另外一件事。当我跟ArrayList源码的时候发现,无论我调用ArrayList哪个带参的构造方法,都会先调用无参构造方法?不知道为什么?也希望能有人帮我解答一下。

  来看看add方法源码:

  

技术分享图片
 1 /**
 2      * Appends the specified element to the end of this list.
 3      *
 4      * @param e element to be appended to this list
 5      * @return <tt>true</tt> (as specified by {@link Collection#add})
 6      */
 7     public boolean add(E e) {
 8         ensureCapacityInternal(size + 1);  // Increments modCount!!
 9         elementData[size++] = e;
10         return true;
11     }
View Code

 

  其实add方法就三个步骤:1.确保ArrayList有足够的容量。2将元素添加到集合末尾(elementData是真正存储元素的数组)。3返回。

  后面两步都很简单,没有什么好说的。在第一步中又主要分为了如下步骤:

  1.方法ensureCapacityInternal(size + 1);

    该方法首先确保ArrayList的容量是从10(DEFAULT_CAPACITY==10)起步的。(对于elementData的描述: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. )

    源码:

技术分享图片
1 private void ensureCapacityInternal(int minCapacity) {
2         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
3             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
4         }
5 
6         ensureExplicitCapacity(minCapacity);
7 }
View Code

  2.ensureExplicitCapacity(int minCapacity)

    明确ArrayList容量是否需要扩容,当需要的存储容量大于ArrayList的实际容量时,就需要通过grow(int minCapacity)进行扩容。

  源码:

技术分享图片
1 private void ensureExplicitCapacity(int minCapacity) {
2         modCount++;
3 
4         // overflow-conscious code
5         if (minCapacity - elementData.length > 0)
6             grow(minCapacity);
7 }
View Code

  3.grow(int minCapacity)

    从代码不难看出,通常ArrayList的容量是按照1.5倍进行扩展的。如果1.5倍的容量还不满足最低扩容需要则按照最低扩容需要进行。如果最低扩容大于ArrayList的MAX_ARRAY_SIZE,则将容量扩至最大。

  源码:

技术分享图片
 1 /**
 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     private void grow(int minCapacity) {
 8         // overflow-conscious code
 9         int oldCapacity = elementData.length;
10         int newCapacity = oldCapacity + (oldCapacity >> 1);
11         if (newCapacity - minCapacity < 0)
12             newCapacity = minCapacity;
13         if (newCapacity - MAX_ARRAY_SIZE > 0)
14             newCapacity = hugeCapacity(minCapacity);
15         // minCapacity is usually close to size, so this is a win:
16         elementData = Arrays.copyOf(elementData, newCapacity);
17 }
View Code

  4.hugeCapacity(int minCapacity)

  源码:

技术分享图片
1 private static int hugeCapacity(int minCapacity) {
2         if (minCapacity < 0) // overflow
3             throw new OutOfMemoryError();
4         return (minCapacity > MAX_ARRAY_SIZE) ?
5             Integer.MAX_VALUE :
6             MAX_ARRAY_SIZE;
7 }
View Code

  5.Arrays.copyOf(elementData, newCapacity)。扩容

  源码:

技术分享图片
 1 public static <T> T[] copyOf(T[] original, int newLength) {
 2         return (T[]) copyOf(original, newLength, original.getClass());
 3 }
 4 
 5 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
 6         @SuppressWarnings("unchecked")
 7         T[] copy = ((Object)newType == (Object)Object[].class)
 8             ? (T[]) new Object[newLength]
 9             : (T[]) Array.newInstance(newType.getComponentType(), newLength);
10         System.arraycopy(original, 0, copy, 0,
11                          Math.min(original.length, newLength));
12         return copy;
13     }
View Code

  ArrayList扩容借助于底层System.arrayCopy方法,该方法属于本地方法。频繁的扩容势必会影响ArrayList的效率。在应用中如果能事先确定ArrayList的大小,那么就按照预知的大小进行初始化,避免初始化的扩容。

 

  

 

ArrayList

标签:分享图片   size   源码   地方法   []   flow   margin   provides   view   

原文地址:http://www.cnblogs.com/tljava/p/8016342.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!