You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请分析两段Java代码片段之间的内存占用差异

两段Java代码的内存占用差异分析

咱们先把两段代码的完整逻辑补全(第二段代码的循环部分应该是重复添加同一个内层列表),再拆解它们的内存差异:

代码示例1

ArrayList<ArrayList<Integer>> outerList = new ArrayList<ArrayList<Integer>>(); 
for(int i=0; i<5000; i++){ 
    outerList.add(new ArrayList<Integer>()); 
    for(int j=0; j<5000; j++){ 
        outerList.get(i).add(1); 
    } 
} 

代码示例2

ArrayList<ArrayList<Integer>> outerList_n = new ArrayList<ArrayList<Integer>>(); 
ArrayList<Integer> innerList_n = new ArrayList<Integer>(); 
for(int j=0; j<5000; j++){ 
    innerList_n.add(1); 
} 
for(int i=0; i<5000; i++){ 
    outerList_n.add(innerList_n); 
} 

核心内存差异分析

这两段代码的本质区别是重复创建对象 vs 复用同一个对象,具体内存开销差异体现在这几个方面:

1. ArrayList对象的数量差异

  • 代码1会创建 5001个ArrayList对象:1个外层列表 + 5000个独立的内层列表(每次循环都new ArrayList<Integer>)。每个ArrayList对象本身会占用内存:包括对象头、size/modCount等元数据、以及指向内部元素数组的引用。
  • 代码2只会创建 2个ArrayList对象:1个外层列表 + 1个内层列表(只初始化一次,之后重复添加它的引用到外层列表)。外层列表里的5000个元素都是指向同一个内层列表的引用,而非新对象。

这直接节省了4999个ArrayList对象的内存开销,这部分差异非常显著。

2. 内部元素数组的内存差异

每个ArrayList内部都有一个elementData数组用于存储元素:

  • 代码1中,5000个内层列表各有自己的elementData数组,每个数组需要容纳5000个Integer引用(虽然1会被Integer缓存复用,所以元素本身是同一个对象,但数组是独立的)。每个数组的长度会扩容到至少5000,所以总共有5000个独立的数组占用内存。
  • 代码2中,只有1个elementData数组存储5000个Integer引用,这部分直接节省了4999个数组的内存开销。

3. 额外注意点

代码2的逻辑存在一个隐性的逻辑差异:因为所有外层列表的元素都指向同一个内层列表,所以如果修改任意一个外层元素对应的内层列表(比如outerList_n.get(0).add(2)),所有其他外层元素对应的列表都会同步变化——这是复用对象带来的逻辑副作用,但从纯内存角度看,它的内存占用远低于代码1。


内容的提问来源于stack exchange,提问作者Aadhirai R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:54:32