19. ArrayList的扩容机制是怎样的?如何优化ArrayList的性能?

ArrayList是基于动态数组实现的,因此其容量是动态调整的。每当ArrayList的容量不足以容纳新的元素时,ArrayList会进行扩容,以确保能够继续添加元素。以下是ArrayList的扩容机制的详细说明:

1. 默认初始容量

  • 当你创建一个ArrayList实例时,如果不指定初始容量,ArrayList的默认初始容量为10

2. 扩容的触发条件

  • 每当ArrayList的当前元素数量达到容量上限时(即添加新元素时,size等于capacity),ArrayList就会触发扩容机制。

3. 扩容的过程

  • 容量的计算 : 当扩容触发时,ArrayList会创建一个新的数组,容量是旧容量的1.5倍(具体来说,新容量 = 旧容量 + 旧容量/2)。

  • 元素的复制 : 然后ArrayList将现有数组中的所有元素复制到新的、更大的数组中。

  • 性能开销: 这个扩容操作涉及到创建一个新的数组,并将所有元素从旧数组复制到新数组中,可能会带来性能上的开销,尤其是当数组非常大时。

4. 扩容后的容量

  • 假设ArrayList的当前容量为10,当你向ArrayList添加第11个元素时,ArrayList会扩容,新的容量将是1510 + 10/2 = 15)。

示例代码

java 复制代码
import java.util.ArrayList;
​
public class ArrayListExpansion {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(10);
        for (int i = 0; i < 12; i++) {
            list.add(i);
        }
        System.out.println("ArrayList size: " + list.size());
    }
}

如何优化ArrayList的性能?

为了提高ArrayList的性能,特别是在处理大量数据时,可以考虑以下优化策略:

1. 指定初始容量

  • 如果你知道ArrayList将要存储的元素数量,建议在创建ArrayList实例时指定一个合适的初始容量。这可以避免频繁的扩容操作,减少不必要的内存复制开销。
java 复制代码
ArrayList<Integer> list = new ArrayList<>(1000); // 预估需要存储1000个元素

2. 避免频繁的增删操作

  • ArrayList在中间插入或删除元素时,需要移动其他元素,导致性能下降。如果需要频繁插入或删除元素,考虑使用LinkedList或其他更适合的集合。

3. 使用trimToSize()方法

  • 如果你在填充完ArrayList后不再需要添加更多元素,可以调用trimToSize()方法,将ArrayList的容量调整为当前元素数量,以节省内存。
java 复制代码
list.trimToSize(); // 调整容量为当前元素数量

4. 减少内存浪费

  • 如果ArrayList中的元素数量可能会大幅减少,可以考虑在删除大量元素后调用trimToSize()来释放多余的内存。

5. 考虑替代数据结构

  • 如果你的应用场景涉及大量的随机插入、删除操作,或者对线程安全有要求,可能需要考虑使用LinkedListCopyOnWriteArrayListConcurrentLinkedQueue等其他集合类。

总结

  • ArrayList的扩容机制 : 当容量不足时,ArrayList会创建一个新数组,容量为原来的1.5倍,并将旧数组中的元素复制到新数组中。

  • 性能优化:

    • 通过指定初始容量来减少扩容次数。

    • 避免频繁的增删操作。

    • 使用trimToSize()方法来释放不必要的内存。

    • 根据具体应用场景,选择适合的集合类型。

这些优化策略可以帮助你在使用ArrayList时获得更好的性能,尤其是在处理大规模数据时。

相关推荐
qq_337763201922 分钟前
国际期货资管系统开发方案|内外盘交易平台源码授权与二次开发支持
java·c语言·开发语言·c++·c#
不定积分要+C_yyy32 分钟前
Java关键字final三种用法、核心特性与高频易错点
java·开发语言
xexpertS2 小时前
队列积压治理:如何避免异步系统出现难以恢复的消息积压
java·开发语言
万少6 小时前
用腻了 WorkBuddy 的默认界面?这个开源小工具给它换上了毛玻璃
前端·javascript·后端
踏月的造梦星球9 小时前
DMDPC 学习:架构、部署、运维与调优
运维·数据库·学习·架构
韩楚风9 小时前
【参天引擎】事务生命周期 / MVCC / Undo / ACID / 分布式事务 功能域整体解析
数据库·分布式·mysql·架构·cantian
阿维的博客日记10 小时前
MultipartFile 是不是表示仅仅是一个分片?
java·后端·spring·multipartfile
renhongxia110 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
海上彼尚10 小时前
Nodejs也能写Agent - 16.LangGraph篇 - 条件分支与循环
前端·后端·langchain·node.js
程序员无隅10 小时前
Coding Agent 为什么压缩上下文后还能继续工作?上下文模块设计拆解
java·开发语言·数据库