ArrayList学习总结——ArrayList构造函数总结

ArrayList

List接口的主要实现类
线程不安全,随机访问元素快,效率高;底层使用Object[] elementDate数组。

源码分析
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

调用无参构造函数时,默认创建长度为10的数组elementDate存储Object类型的数据

list.add(元素1);	//elementData[0] = new Object(元素);
...
...
list.add(元素n);	//如果此次的添加导致底层elementData数组容量不够,则扩容

扩容机制

    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);
    }
// 扩容:10(调用无参构造时默认的大小),15,22,33,...

默认情况下,当数组长度不够时扩容到原长度的1.5倍,同时将原有数组中的数据复制到新的数组中。当扩容达到最大值时仍需要扩容,则抛异常,最大值为Integer.MAX_VALUE - 8

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

然而下列源码颠覆我的认知,让我有点懵:

    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:
        // minCapacity的大小 通常接近size的大小,所以下列代码执行:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

	// 当minCapacity 小于0时,内存溢出;
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

并且,在调用构造函数创建ArrayList对象时,传入一个Integer.MAX_VALUE是会出现错误的java.lang.OutOfMemoryError: Requested array size exceeds VM limit;只有当传入参数为Integer.MAX_VALUE - 2以及减去更大的值时才是java.lang.OutOfMemoryError: Java heap space内存限制。Integer.MAX_VALUE - 2是我的虚拟机限制数组大小的临界值。
创建ArrayList时,在知道数据多少的情况下,推荐使用带参构造函数,避免数组长度不够时进行的扩容行为。

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

当初始长度大于0时,创建数组,长度为initialCapacity = 10;
当初始长度为0时,创建数组,长度为EMPTY_ELEMENTDATA;
否则抛出IllegalArgumentException异常。

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

构造一个包含指定collection的元素的列表,这些元素是按照该collection的迭代器返回她们的顺序排列的。
将collection对象传入,并将其转换为名为elementData的数组
当数组长度不为0,且数组的类型与Object[]数组的类型不同时, 复制elementData数组,截取或用 null 填充(如有必要),以使副本具有指定的长度;
当数组长度等于0时,创建一个名为elementData的数组,其长度为EMPTY_ELEMENTDATA的长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值