Java集合“坑王”:ArrayList为啥越界还能浪?

提起ArrayList,新手总觉得它就是个"自动扩容的数组",随便add、get都不怕------直到遇到 IndexOutOfBoundsException ,才发现这货藏着不少小心机。今天咱扒一扒ArrayList的扩容黑科技,以及那些让你踩坑的细节!

一、先搞懂:ArrayList为啥能"自动变长"?

ArrayList底层是普通数组,默认初始容量是10。当添加元素导致数组满了,它会悄悄扩容:新容量=旧容量×1.5(源码里是 oldCapacity + (oldCapacity >> 1) ),然后把旧数组的数据复制到新数组。

看个简单例子,直观感受扩容:

java 复制代码
import java.util.ArrayList;

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(); // 初始容量10
        
        // 加10个元素,刚好填满初始数组
        for (int i = 0; i < 10; i++) {
            list.add("元素" + i);
        }
        
        // 第11个元素:触发扩容!新容量变成15
        list.add("触发扩容的元素");
        
        System.out.println("当前元素数量:" + list.size()); // 输出11
        System.out.println("能存但未用的容量:" + (list.size() < 15 ? 15 - list.size() : "已再次扩容")); // 输出4
    }
}

二、踩坑重灾区:size和capacity别搞混!

很多人以为 list.size() 是数组容量,其实大错特错:

  • size() :实际存储的元素数量(你add了多少个)
  • capacity :底层数组的长度(ArrayList内部用 elementData 数组,容量不对外暴露)

这就是为啥 get(10) 会报错------哪怕数组容量是15,只要你只存了11个元素,索引10是有效的,但索引11就越界:

java 复制代码
public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    for (int i = 0; i < 11; i++) {
        list.add("元素" + i);
    }
    
    System.out.println(list.get(10)); // 正常输出:元素10
    list.get(11); // 直接抛IndexOutOfBoundsException!
}

三、实用技巧:提前指定容量,避免频繁扩容

如果知道要存多少元素,初始化时直接指定容量,能减少数组复制的性能损耗:

java 复制代码
// 已知要存1000个元素,直接指定容量
ArrayList<String> list = new ArrayList<>(1000);
// 后续add1000个元素,一次扩容都不会触发

最后划重点

  1. ArrayList扩容是"偷偷摸摸"的,扩容后旧数组会被GC回收;

  2. 越界异常看的是 size() ,不是底层数组容量;

  3. 大数据量场景一定要指定初始容量,优化性能。

相关推荐
云烟成雨TD19 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
于慨19 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz19 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
swg32132119 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
从前慢丶19 小时前
前端交互规范(Web 端)
前端
gelald20 小时前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川20 小时前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月20 小时前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
CHU72903520 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
chenjingming66620 小时前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter