JDK7 和JDK8的ArrayList的区别对比

时间:2023-01-08 19:58:18

示例

public class ArrayListTest {
    public static void main(String[] args) {
        ArrayList<Object> jdk = new ArrayList<>();
        jdk.add(123);
    }
}

初始化操作

①调用无参构造器

jdk7从无参调用有参构造器,并初始化为10:

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
   this(10);
}

/**
 * Constructs an empty list with the specified initial capacity.
 *
 * @param  initialCapacity  the initial capacity of the list
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
}

jdk8将其定义为长度为零的空数组,在之后的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 = {};

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

添加操作

①调用add(E e)方法,jdk7源码与jdk8源码一致

/**
 * 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) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

②调用ensureCapacityInternal(int minCapacity)方法,jdk7源码与jdk8源码不同

jdk7如果加入元素后的个数大于数组长度则扩容(eg.在采用无参构造器初始化,添加到11个元素时会扩容)

private void ensureCapacityInternal(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

jdk8如果采用时默认初始化则数组elementData为DEFAULTCAPACITY_EMPTY_ELEMENTDATA,而第一次调用add时,minCapacity为1,DEFAULT_CAPACITY为10, minCapacity取两个中的最大值10,然后调用ensureExplicitCapacity会将数组elementData会在添加第一个元素时初始化大小为10

/**
 * Default initial capacity.
 */
private static final int DEFAULT_CAPACITY = 10;


private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

③扩容机制,一般情况下(不走if)扩容为1.5倍,特殊情况1(第一个if)当newCapacity<minCapacity时采用minCapacity的容量(eg.jdk8就是采用了该规则,传入minCapacity为10,默认elementData.length为0优化代码),特殊情况2(第二个if)如果扩容后的newCapacity 大于了ArrayList规定的最大值MAX_ARRAY_SIZE 则会传入miniCapacity值采用hugeCapacity方法获取数组大小(尽量不让其出现OutOfMemoryError),jdk7源码与jdk8源码一致

/**
 * 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;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 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;
}