不规则二维数组节省内存的根本原因是每行仅分配实际所需空间,避免统一按最大行宽分配造成的浪费;其底层为引用数组加独立堆块,无填充字节,遍历时须依各行真实长度操作。

Java 不规则二维数组(又称锯齿数组)之所以能提升存储空间利用率,根本原因在于它避免了“按最大行宽统一分配”的内存浪费。它不是一块连续的矩形内存块,而是由多个独立、长度各异的一维数组拼接而成——每行只申请自己真正需要的空间。
不规则数组如何节省内存
假设要存储三个班级的学生人数:一班25人、二班32人、三班28人。
- 用规则二维数组 int[3][32]:需分配 3 × 32 = 96 个 int 单元,其中一班多占7个、三班多占4个,共浪费11个单元;
- 用不规则数组 int[3][] 并分别赋值:arr[0] = new int[25]、arr[1] = new int[32]、arr[2] = new int[28]:仅分配 25 + 32 + 28 = 85 个单元,零冗余;
- 若数据差异更大(如某行仅1个元素,另一行需200个),节省比例会更显著——尤其在稀疏或阶梯状结构(如杨辉三角、树形路径)中优势突出。
底层内存结构决定空间灵活性
不规则数组本质是“一维引用数组 + 多个独立堆块”:
- 声明 int[][] arr = new int[3][]:仅在堆中创建一个含3个 null 引用的数组(大小固定,约24字节);
- 后续 arr[0] = new int[25] 等操作:为每行单独在堆中开辟一段连续内存,彼此地址不连续、互不影响;
- 没有预设列数约束,因此不会因“对齐”或“补齐”产生填充字节,也无需预留空位应对未来扩展(除非业务真有动态扩容需求)。
遍历时必须匹配每行真实长度
误用固定列数会导致越界或跳过数据:
立即学习“Java免费学习笔记(深入)”;
- ❌ 错误写法:for (int j = 0; j —— 第0行只有25个元素,访问 arr[0][30] 直接抛 ArrayIndexOutOfBoundsException;
- ✅ 正确写法:for (int j = 0; j —— 每次取当前行实际长度,安全且精准;
- 静态初始化时(如 int[][] j = {{1}, {2,3,4}, {5,6}}),各子数组长度天然不同,j[0].length == 1、j[1].length == 3、j[2].length == 2,必须逐行读取。
适用场景与使用提醒
适合数据天然不等长、变化频繁或内存敏感的场景:
- 学生成绩表(各班人数不同)、文本分词结果(每句词数不等)、JSON嵌套数组解析、图的邻接表表示;
- 注意空行风险:若某行未初始化(如漏写 arr[2] = new int[28]),arr[2] 值为 null,直接访问 arr[2][0] 抛 NullPointerException;
- 不适用于高频列运算(如求每列平均值),因其内存非连续,列访问缓存不友好——此时应考虑转置为规则结构或改用一维数组+索引计算。


















