ArrayList的底层

ArrayList在执行remove或add操作时,可能需要对数组进行扩容。它会基于当前旧数组的长度计算新容量,通常是旧长度的1.5倍。如果新容量小于需求量,会进行特殊处理,包括检查最小容量和处理溢出情况。当超过最大数组大小时,可能会返回Integer.MAX_VALUE。

ArrayList:基于数组实现,调用remove(Object o),add()方法时,在底层其实是重新拷贝了一个数组以remove(Object o)举例。

ArrayList的所有操作都是基于数组实现,在我们要在List中添加一个元素的时候,底层会去对数组进行一个扩容,就是重新copy一个数组,而新数组的长度就是旧数组的length+1。他会对这个新数组的长度进行以下判断:

1.他会根据旧数组的长度进行一个判断,newCapactiy(旧数组de length+旧数组的length >> 1 (相当于*2))。如果newCapactiy - 新数组的长度 <=0会进入第二层判断,如果是一个空数组就返回Math.max(DEFAULT_CAPACITY, minCapacity)DEFAULT_CAPACITY=10,minCapacity就是旧数组length+1。如果minCapacity < 0 就抛出异常。如果这两个条件都不满足的话就返回minCapacity。

 int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity <= 0) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return minCapacity;
        }

2.如果不满足条件1的第一层判断的话就会返回以下的内容,MAX_ARRAY_SIZE是Interge.Max -8

return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);
hugeCapacity(minCapacity)又会进入判断。如果minCapacity < 0抛出异常。如果minCapacity>MAX_ARRAY_SIZE 就会返回Interge.Max_value,反之就返回Interge.Max -8
private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE)
            ? Integer.MAX_VALUE
            : MAX_ARRAY_SIZE;
    }

### Java `ArrayList` 底层实现机制 #### 数组结构基础 `ArrayList` 的核心在于其内部维护了一个对象数组 `elementData` 来存储元素。当创建一个新的 `ArrayList` 实例而未指定初始容量时,默认情况下该列表并不立即分配内存空间,而是通过一个名为 `DEFAULTCAPACITY_EMPTY_ELEMENTDATA` 的占位符来表示空状态[^3]。 一旦向此集合添加第一个元素,则会触发初始化过程并自动调整至默认大小(通常是10)。如果指定了具体的构造参数以设定起始容量,则会在实例化阶段就完成相应规模的数组开辟操作。 ```java private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList(int initialCapacity) { super(); if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } ``` #### 动态扩展特性 随着不断追加新成员到 `ArrayList` 中,最终可能会超出当前可用的空间范围。此时便会启动扩容流程:构建更大尺寸的新数组并将旧有数据迁移过去;新的长度通常为原长的一半再加原来的长度即 `(oldCapacity >> 1) + oldCapacity` 或者直接翻倍取决于JDK版本以及具体情况下的优化策略[^2]。 为了提高效率,在某些场景下还会预先多预留一些额外位置以便后续连续写入而不必频繁执行上述耗时的操作: ```java int newCapacity = oldCapacity + (oldCapacity >> 1); // 增量大约等于原来一半 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); this.elementData = Arrays.copyOf(this.elementData, newCapacity); ``` #### 容量规划考量 考虑到性能因素,合理设置容器初识容量可以有效减少不必要的复制开销。对于已知大致数量级的应用场合建议显式给出预期值从而避免潜在瓶颈问题的发生。 此外值得注意的是尽管提供了灵活的增长方式但也意味着随机访问具备O(1)时间复杂度优势的同时插入删除动作特别是在头部附近将会带来线性级别的成本增加因此需权衡选用合适的数据结构满足特定需求[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值