JDK8和JDK19 arraylist源码区别

 JDK8 

add()方法

通过无参构造ArrayList之后

        当我们add()添加一个元素的时候,先执行ensureCapaCityInternal 并且由于初始化是一个空数组所以size是0,此时方法就是ensureCapaCityInternal(0+1)

        然后去执行ensureExplicitCapacity(),这个方法的参数需要先执行calculateCapacity() 并且传入 两个参数 其中minCapacity就是size+1的值也就是1,但同时由于是刚初始化的数组,此时elementData 这个数组是一个空数组并进行判断,返回传入的最小容量和默认容量取大值,那么第一次就会返回10 即默认的容量

        ensureExplicitCapacity()方法此时的参数就是10,进入方法minCapacity-elementData.length>0就成立 开始执行扩容grow(minCapacity)操作(初始化添加元素执行第一次扩容)


private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;


private void grow(int minCapacity) {
  
    int oldCapacity = elementData.length;
  
    int newCapacity = oldCapacity + (oldCapacity >> 1);

    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
   
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);

    elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容操作

        获取旧数组容量0

        获取新数组容量 = 旧数组容量+旧数组容量带符号右移一位 = 旧数组容量+旧数组容量除以2 =1.5旧数组容量 第一次也是0

        判断新数组容量是否小于的最小容量,如果小于那么最小容量就是新数组的容量(0-10<0)

此时新容量就是10,第一次扩容完毕

        add()第二个元素 执行到calculateCapacity()里面发现现在数组容量是10 不满足条件所以不扩容

        一直到第10个元素 此时minCapcity是11 elementData.length是10,再次扩容

        grow()里获取老容量10 新容量是1.5倍老容量也就是15 新容量此时肯定大于最小容量 所以判断新容量和最大容量哪个大,此时并不大与所以也不执行hugeCapacity

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
   
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

其实hugeCapacity就是做了一个容量判断 ,最小容量是否,超过了最大值Integer.MAX_VALUE - 8;超过了的话 他就是Integer的最大值,否则就是Integer.MAX_VALUE - 8;

JDK19

        在ArrayList初始化两个版本没有变化,都是有三个构造器

        add()

        

private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 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 = {};

    /**
     * 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

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

    /**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
    }


    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

add()里面又调用了一个3参的add(),此时add(e,0,0),初始s=0 elementData.length =0,直接扩容

 private Object[] grow() {
        return grow(size + 1);
    }


private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

        扩容

                第一个元素进来 minCapacity = 1  oldCapacity = 0 直接进入else 创建一个默认大小10的数组

        当第二个元素进来,add()里直接在数组上添加元素直到第10个,发现数组大小和元素个数相等,又开始扩容,此时grow()里 oldCapacity = 10  进入if 里面有个 ArraysSupport.newLength()

     public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;

    public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // preconditions not checked because of inlining
        // assert oldLength >= 0
        // assert minGrowth > 0

        int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
        if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
            return prefLength;
        } else {
            // put code cold in a separate method
            return hugeLength(oldLength, minGrowth);
        }
    }

传入10,1,5这三个参数(针对添加第11个元素来说) 此时prefLength = 15(还是扩容1.5),此时直接return prefLength作为扩容大小,调用Arrays.copy(),拷贝数组,Arrays.copy()底层又调用了System.arraycopy()对数组进行拷贝

private static int hugeLength(int oldLength, int minGrowth) {
        int minLength = oldLength + minGrowth;
        if (minLength < 0) { // overflow
            throw new OutOfMemoryError(
                "Required array length " + oldLength + " + " + minGrowth + " is too large");
        } else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {
            return SOFT_MAX_ARRAY_LENGTH;
        } else {
            return minLength;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值