ArrayList

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拥有数组元素有序的特点。

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

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的大小,那么就按照预知的大小进行初始化,避免初始化的扩容。

 

  

 

转载于:https://www.cnblogs.com/tljava/p/8016342.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值