在 Java 中,List<int[]>()
和 List<int[]>[]
是两种不同的数据结构,它们的区别主要体现在维度和用途上:
1. List<int[]>()
- 本质:一维动态数组,每个元素是一个整数数组(
int[]
)。 - 声明方式:
List<int[]> list = new ArrayList<>();
- 特点:
- 动态大小:可随时添加 / 删除元素。
- 元素类型:每个元素是一个整数数组(如
[1, 2]
、[3, 4, 5]
)。
- 用途:存储多个数组,适合表示二维数据或关联数据。
2. List<int[]>[]
- 本质:二维固定大小数组,每个元素是一个整数数组列表(
List<int[]>
)。 - 声明方式:
List<int[]>[] array = new ArrayList[n]; // n 为数组长度
- 特点:
- 固定大小:数组长度
n
必须在创建时指定。 - 元素类型:每个元素是一个
List<int[]>
,需手动初始化每个列表。
- 固定大小:数组长度
- 用途:存储多个列表,适合表示分组数据或图的邻接表。
核心区别对比表
特性 | List<int[]>() |
List<int[]>[] |
---|---|---|
本质 | 一维动态列表 | 二维固定大小数组 |
元素类型 | 每个元素是 int[] |
每个元素是 List<int[]> |
动态扩容 | 支持(自动扩容) | 不支持(数组长度固定) |
初始化方式 | new ArrayList<>() |
new ArrayList[n] |
元素初始化 | 自动初始化(空列表) | 需手动初始化每个列表 |
典型用途 | 存储二维数据(如坐标点) | 图的邻接表、分组数据 |
访问方式 | list.get(i)[j] |
array[i].get(j)[k] |
1. List<int[]>()
的例子:存储二维坐标点
场景:存储多个二维坐标点(x, y)。
// 创建一个列表,每个元素是一个坐标点 [x, y]
List<int[]> points = new ArrayList<>();
// 添加三个坐标点
points.add(new int[]{0, 0}); // 原点
points.add(new int[]{1, 2}); // 点 (1, 2)
points.add(new int[]{3, 4}); // 点 (3, 4)
// 访问第二个点的 x 坐标
int x = points.get(1)[0]; // 1
int y = points.get(1)[1]; // 2
// 动态添加新点
points.add(new int[]{5, 6}); // 点 (5, 6)
数据结构示意图:
points = [
[0, 0], // 索引0:原点
[1, 2], // 索引1:点(1, 2)
[3, 4], // 索引2:点(3, 4)
[5, 6] // 索引3:新增点(5, 6)
]
2. List<int[]>[]
的例子:图的邻接表
场景:表示一个有向图,每个节点的邻居及其边的权重。
// 创建一个长度为3的数组,每个元素是一个邻接表
List<int[]>[] graph = new ArrayList[3];
// 初始化每个节点的邻接表
for (int i = 0; i < 3; i++) {
graph[i] = new ArrayList<>();
}
// 添加边:节点0 -> 节点1,权重为10
graph[0].add(new int[]{1, 10});
// 添加边:节点0 -> 节点2,权重为20
graph[0].add(new int[]{2, 20});
// 添加边:节点1 -> 节点2,权重为30
graph[1].add(new int[]{2, 30});
// 访问节点0的第一个邻居及其权重
int neighbor = graph[0].get(0)[0]; // 1
int weight = graph[0].get(0)[1]; // 10
数据结构示意图:
graph = [
// 节点0的邻居:节点1(权重10)、节点2(权重20)
[ [1, 10], [2, 20] ],
// 节点1的邻居:节点2(权重30)
[ [2, 30] ],
// 节点2没有出边
[]
]
3. 对比:存储班级学生成绩
使用 List<int[]>()
场景:一个班级的所有学生成绩(每个学生有多门课成绩)。
// 创建一个列表,每个元素是一个学生的成绩数组
List<int[]> classScores = new ArrayList<>();
// 添加三个学生的成绩
classScores.add(new int[]{85, 90, 92}); // 学生1:三门课成绩
classScores.add(new int[]{76, 88}); // 学生2:两门课成绩
classScores.add(new int[]{95, 89, 94}); // 学生3:三门课成绩
// 访问第二个学生的第一门课成绩
int score = classScores.get(1)[0]; // 76
使用 List<int[]>[]
场景:多个班级的学生成绩(每个班级有多个学生,每个学生有多门课成绩)。
// 创建一个长度为2的数组,表示两个班级
List<int[]>[] allClasses = new ArrayList[2];
// 初始化每个班级的学生列表
for (int i = 0; i < 2; i++) {
allClasses[i] = new ArrayList<>();
}
/** 使用 Arrays.setAll 初始化每个班级的学生列表
Arrays.setAll(allClasses, i -> new ArrayList<>());
**/
// 向班级0添加学生成绩
allClasses[0].add(new int[]{85, 90, 92}); // 班级0的学生1
allClasses[0].add(new int[]{76, 88}); // 班级0的学生2
// 向班级1添加学生成绩
allClasses[1].add(new int[]{95, 89, 94}); // 班级1的学生1
// 访问班级1的第一个学生的第二门课成绩
int score = allClasses[1].get(0)[1]; // 89
4. 关键区别总结
特性 | List<int[]>() |
List<int[]>[] |
---|---|---|
维度 | 一维(动态列表) | 二维(固定大小数组 + 动态列表) |
存储内容 | 多个数组(如坐标点、成绩) | 多个列表(如分组数据、图的邻接表) |
动态扩容 | 支持(自动扩容) | 仅列表部分支持扩容,数组长度固定 |
访问方式 | list.get(i)[j] |
array[i].get(j)[k] |
典型场景 | 二维数据(行数不固定) | 分组数据、图结构 |
通过这些例子,可以更直观地理解两种结构的适用场景:
List<int[]>()
适合存储多个同类型数组(如多个坐标点、多个学生成绩)。List<int[]>[]
适合将数据按组划分(如多个班级、图的多个节点),每组内再存储多个数组。