Java不规则二维数组本质是“一维数组的数组”,每行长度可不同、可为空或null;需在访问前判空、取长前确认存在且足够长,初始化分两步(外层声明行数、内层逐行赋值),遍历用传统双层for更安全,动态场景优先用List<List<T>>,边界校验建议封装工具方法。

Java 不规则二维数组本质是“一维数组的数组”,每行长度可不同、可为空甚至为 null。处理变长数据集合时,硬套规则矩阵逻辑极易引发 NullPointerException 或 ArrayIndexOutOfBoundsException。关键不是“怎么写得快”,而是“怎么写得稳”——每次访问子数组前判空,每次取长度或下标前确认存在且足够长。
初始化:按需分配,避免提前假设
不规则结构的核心优势在于灵活适配真实数据(如用户标签列表、日志事件序列、稀疏表格)。初始化必须分两步走:
-
外层声明行数:用
new Type[rows][]只分配行引用空间,不碰列 -
内层逐行赋值:根据实际数据长度,单独为每行
new Type[length]
例如读取 CSV 行字段数不一时:
String[][] data = new String[lineCount][]; // 外层只定行数
for (int i = 0; i < lineCount; i++) {
String[] fields = parseLine(i); // 每行字段数可能不同
data[i] = fields; // 直接赋值,长度由 fields.length 决定
}
遍历:传统 for 循环最可靠
增强 for 虽简洁,但丢失索引且对 null 行更敏感;传统双层 for 易控边界、支持修改、语义清晰:
立即学习“Java免费学习笔记(深入)”;
- 外层判断
i < arr.length防越行 - 进入内层前加
if (arr[i] != null)防空指针 - 内层条件用
j < arr[i].length,绝不用arr[0].length
安全打印示例:
for (int i = 0; i < arr.length; i++) {
if (arr[i] != null) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + "\t");
}
}
System.out.println(); // 每行结束后换行
}
扩容与动态增长:优先用 List<List<T>>
原始二维数组扩容成本高、易出错。真实业务中变长集合更适合用嵌套集合:
List<List<String>> jagged = new ArrayList<>();- 添加新行:
jagged.add(new ArrayList<>()); - 向某行追加:
jagged.get(rowIdx).add("item");—— 自动扩容,无需手动复制数组
若必须用数组(如 JNI 交互或性能敏感场景),扩容需分步:Arrays.copyOf() 扩外层,再对目标行单独 Arrays.copyOf() 扩内层,并始终检查 arr[i] != null。
边界校验:封装成工具方法防踩坑
重复手写判空和长度检查易遗漏。建议封装通用工具:
-
safeGet(arr, row, col):返回元素或默认值,内部检查row和col合法性 -
ensureRow(arr, row):若arr[row] == null则初始化为空数组 -
maxColumnCount(arr):遍历求最大列宽,用于列优先展示等场景
这类方法把“防御性编程”固化下来,比每次手动加 if 更可持续。
不复杂但容易忽略


















