ArrayList common data structures

Foreword

    ArrayList is presumably the majority of Java programmers to develop the most commonly used data structures, but does not necessarily have to understand its principles, and today I will combine them to explain the source ArrayList. This article will focus on the main characteristics of the ArrayList (including applicable scene, initial size, expansion, etc.), data storage methods, the core way to achieve, other characteristics of four aspects to explain.

A, ArrayList properties

    ArrayList data structure is based on the array, as compared with the LinkedList, is more suitable for multi-query, using the following small deletions operating scenarios, it is not thread-safe and, if larger than concurrent scenario, the need to switch or thread-safe versions JUC package with CopyOnWriteArrayList.

    Its initial size of the array 10, controlled by a member variable as shown below:

 

     When the newly added elements of the original array have been filled, expansion is triggered, the original array of length expansion strategy * 1.5, the code is implemented using a right shift operation, the source code as follows:

Second, the data storage method

    ArrayList by way of an array of stored data, Object [], as follows:

Third, the core way to achieve

    We look at the most commonly used method add:

. 1  public  Boolean the Add (E E) {
 2          ensureCapacityInternal (size +. 1);   // if full, the capacity expansion 
. 3          elementData of [size ++] = E;
 . 4          return  to true ;
 . 5      }

    The following method is used to determine whether the original array is full, if the full expansion, dissatisfied uninitialized initializing a length of 10, otherwise no change

1 private void ensureCapacityInternal(int minCapacity) {
2         ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
3     }

    下面方法用于返回数组需要的最小长度。

1 private static int calculateCapacity(Object[] elementData, int minCapacity) {
2         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
3             return Math.max(DEFAULT_CAPACITY, minCapacity);
4         }
5         return minCapacity;
6     }

    下面的方法用于判断是否需要扩容,如果需要则通过grow方法扩容。

1 private void ensureExplicitCapacity(int minCapacity) {
2         modCount++;
3 
4         // overflow-conscious code
5         if (minCapacity - elementData.length > 0) // 如果需要的最小长度大于当前数组总长度,则走grow扩容
6             grow(minCapacity);
7     }

    下面的grow方法是控制扩容的核心方法:

 1 private void grow(int minCapacity) {
 2         // overflow-conscious code
 3         int oldCapacity = elementData.length;
 4         int newCapacity = oldCapacity + (oldCapacity >> 1);
 5         if (newCapacity - minCapacity < 0) // 如果扩容之后的长度小于需要的最小长度,则取最小长度为待扩容长度,这种情况一般不会出现
 6             newCapacity = minCapacity;
 7         if (newCapacity - MAX_ARRAY_SIZE > 0)
 8             newCapacity = hugeCapacity(minCapacity);
 9         // minCapacity is usually close to size, so this is a win:
10         elementData = Arrays.copyOf(elementData, newCapacity); // 创建新数组,将老数组的数据复制过去
11     }

    注意复制数组时,用的Arrays.copyOf方法,该方法最终引用的是System.arraycopy这个native方法实现的数组复制。其他方法更加简单,此处就不一一粘贴源码解读了。

四、其他特性

1、关于modCount

    在看ArrayList源码的时候,会发现有一个变量是modCount,在增删改的方法中均涉及到对它的++操作。modCount属性是在AbstractList中定义出来的:

 

    可以把它理解成每个ArrayList的一个改动的版本号,只要ArrayList有改动,这个版本号就会+1。在通过迭代器对ArrayList里面的元素进行遍历操作时,每次都会比较一下这个版本号是否有变化,如果检测到预期之外的变化,就会抛出常见的那个异常-ConcurrentModificationException:

 

    ArrayList东西不多,实现也相对比较简单,面试时现在一般会跟Vector或者LinkedList进行比对或者作为多线程的一个引子来问,本文就先到这里,下一期对LinkedList进行解读。

Guess you like

Origin www.cnblogs.com/zzq6032010/p/11980292.html