很多从C/C++转过来的开发者以为Java的二维数组是真正的矩形内存块,这篇真实验证它的本质——一个数组,元素恰好也是数组,每一行真实都是独立创建、可以是任意长度的对象。
上一篇:Collectors.groupingBy() 真实验证
手动给二维数组的每一行分配不同长度的内层数组,验证是否真的允许。
JaggedArrayDemo.java int[][] jagged = new int[4][]; // 只分配外层 jagged[0] = new int[]{1}; jagged[1] = new int[]{1, 2}; jagged[2] = new int[]{1, 2, 3}; jagged[3] = new int[]{1, 2, 3, 4};
真实验证每行长度不同: jagged[0].length 真实是: 1 jagged[1].length 真实是: 2 jagged[2].length 真实是: 3 jagged[3].length 真实是: 4
真实结果证明了 Java 二维数组的本质:int[][] 类型真实就是"元素类型为 int[] 的数组",外层数组的每个元素只是一个指向某个 int[] 对象的引用,这些内层数组彼此完全独立,长度真实可以任意不同——这和 C 语言里 int[4][4] 分配一整块连续矩形内存的模型是完全不同的两种设计。
用new int[3][4]这种看起来是矩形的写法创建数组,验证每一行是否真的是独立对象。
JaggedArrayDemo.java int[][] rectangular = new int[3][4]; rectangular[1] = new int[10]; // 事后把某一行替换成不同长度
rectangular[0] == rectangular[1] 真实结果: false(每行都是真实独立的数组对象,不是共享同一行) 替换后 rectangular[1].length 真实是: 10(其他行仍是4) rectangular[0].length 真实保持: 4
锯齿数组不只是一个语言特性,在真实需要三角形/不规则结构数据的场景下,能真实避免浪费内存。
JaggedArrayDemo.java int[][] triangle = new int[rows][]; for (int i = 0; i < rows; i++) { triangle[i] = new int[i + 1]; // 每行长度真实递增 triangle[i][0] = triangle[i][i] = 1; for (int j = 1; j < i; j++) triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j]; }
真实杨辉三角(锯齿数组实现): [1] [1, 1] [1, 2, 1] [1, 3, 3, 1] [1, 4, 6, 4, 1] n=1000 时,完整矩形需要存储元素数: 1000000,锯齿三角形只需要: 500500(真实节省约50.0%)
真实结果验证了杨辉三角(帕斯卡三角)这种天然的三角形结构,用锯齿数组存储真实计算正确,而且每一行只分配真正需要的长度,不像用完整矩形数组(int[n][n])那样浪费掉上三角部分永远用不到的空间。对于 n=1000 的场景,真实计算出锯齿存储只需要约一半的元素空间——这是锯齿数组在真实工程场景(邻接表存储图结构、动态规划里的三角形状态表)里的真实价值所在。
每一行都是真实运行这段代码得到的结果。