杰瑞科技汇

Java ArrayList如何创建二维数组?

在 Java 中,没有真正的“二维 ArrayList”这种原生数据类型,我们通常使用 ArrayListArrayList,也就是一个 ArrayList 里面存放的是其他的 ArrayList,每个内部的 ArrayList 代表一行,而内部的元素则代表该行中的列。

Java ArrayList如何创建二维数组?-图1
(图片来源网络,侵删)

声明和初始化

创建一个二维 ArrayList 通常有两种方式:动态扩容和指定初始大小。

动态扩容(最常用)

这种方式从一个空的 ArrayList 开始,然后根据需要动态添加行和列。

// 1. 声明一个外部的 ArrayList,它将存储 ArrayList<Integer> 类型的对象(即行)
ArrayList<ArrayList<Integer>> twoDArrayList = new ArrayList<>();
// 2. 添加第一行
ArrayList<Integer> row1 = new ArrayList<>();
row1.add(1);
row1.add(2);
row1.add(3);
twoDArrayList.add(row1);
// 3. 添加第二行
ArrayList<Integer> row2 = new ArrayList<>();
row2.add(4);
row2.add(5);
row2.add(6);
twoDArrayList.add(row2);
// 4. 添加第三行(这一行只有两个元素)
ArrayList<Integer> row3 = new ArrayList<>();
row3.add(7);
row3.add(8);
twoDArrayList.add(row3);
// twoDArrayList 的结构是:
// [
//   [1, 2, 3],
//   [4, 5, 6],
//   [7, 8]
// ]

预定义行数和列数

如果你知道最终的行数和列数,可以先创建一个固定大小的框架,然后再填充数据,这类似于传统二维数组的初始化。

int rows = 3;
int cols = 4;
// 1. 创建一个包含 'rows' 个空 ArrayList 的外部 ArrayList
ArrayList<ArrayList<String>> matrix = new ArrayList<>(rows);
// 2. 使用循环为每一行创建一个新的 ArrayList 并添加到外部 ArrayList 中
for (int i = 0; i < rows; i++) {
    // 为每一行创建一个内部 ArrayList
    ArrayList<String> row = new ArrayList<>(cols); // 预分配列数可以提高性能
    matrix.add(row);
    // 向这一行中添加元素
    for (int j = 0; j < cols; j++) {
        row.add("Element-" + i + "-" + j);
    }
}
// matrix 的结构是:
// [
//   [Element-0-0, Element-0-1, Element-0-2, Element-0-3],
//   [Element-1-0, Element-1-1, Element-1-2, Element-1-3],
//   [Element-2-0, Element-2-1, Element-2-2, Element-2-3]
// ]

访问元素

访问元素使用 get() 方法进行两次嵌套。

Java ArrayList如何创建二维数组?-图2
(图片来源网络,侵删)
  • outerList.get(i) 获取第 i 行(这是一个内部的 ArrayList)。
  • 然后对这个内部列表调用 .get(j) 获取第 j 列的元素。

注意: Java 的索引从 0 开始。

// 假设我们使用方式一创建的 twoDArrayList
int element = twoDArrayList.get(0).get(1); // 获取第一行第二列的元素 -> 2
System.out.println("元素是: " + element); // 输出: 元素是: 2
String element2 = matrix.get(1).get(2); // 获取第二行第三列的元素 -> "Element-1-2"
System.out.println("元素是: " + element2); // 输出: 元素是: Element-1-2

安全访问: 像传统数组一样,访问前最好检查索引是否越界,以避免 IndexOutOfBoundsException

int i = 2;
int j = 1;
if (i < twoDArrayList.size() && j < twoDArrayList.get(i).size()) {
    System.out.println("安全访问的元素: " + twoDArrayList.get(i).get(j));
} else {
    System.out.println("索引越界!");
}

修改元素

修改元素同样使用两次 get() 来定位,然后使用 set() 方法。

// 将 twoDArrayList 中第一行第二列的元素从 2 修改为 99
twoDArrayList.get(0).set(1, 99);
// 修改后,twoDArrayList 的结构变为:
// [
//   [1, 99, 3],
//   [4, 5, 6],
//   [7, 8]
// ]
System.out.println("修改后的元素: " + twoDArrayList.get(0).get(1)); // 输出: 修改后的元素: 99

遍历二维 ArrayList

有几种常见的遍历方式。

Java ArrayList如何创建二维数组?-图3
(图片来源网络,侵删)

使用传统的 for 循环

System.out.println("--- 使用 for 循环遍历 ---");
for (int i = 0; i < twoDArrayList.size(); i++) {
    // 获取当前行
    ArrayList<Integer> currentRow = twoDArrayList.get(i);
    for (int j = 0; j < currentRow.size(); j++) {
        System.out.print(currentRow.get(j) + " ");
    }
    System.out.println(); // 换行
}

使用增强 for 循环(更简洁、推荐)

这种方式代码更易读。

System.out.println("\n--- 使用增强 for 循环遍历 ---");
for (ArrayList<Integer> row : twoDArrayList) {
    for (Integer element : row) {
        System.out.print(element + " ");
    }
    System.out.println();
}

添加和删除行/列

添加行

直接使用外层 ArrayListadd() 方法。

// 在末尾添加一行
ArrayList<Integer> newRow = new ArrayList<>();
newRow.add(10);
newRow.add(11);
twoDArrayList.add(newRow);
// 在指定位置插入一行(在第1行和第2行之间插入)
ArrayList<Integer> anotherRow = new ArrayList<>();
anotherRow.add(20);
anotherRow.add(21);
twoDArrayList.add(1, anotherRow); // 在索引 1 的位置插入

删除行

直接使用外层 ArrayListremove() 方法。

// 删除最后一行
twoDArrayList.remove(twoDArrayList.size() - 1);
// 删除指定索引的行(删除索引为 1 的行)
twoDArrayList.remove(1);

添加/删除列

“列”的概念不那么直接,因为每一行的长度可以不同。

  • 添加列: 需要遍历每一行,并在每一行的末尾(或指定位置)添加一个元素。
  • 删除列: 同样需要遍历每一行,并从每一行中删除指定位置的元素。
// 在每一行的末尾添加一个新列,值为 0
for (ArrayList<Integer> row : twoDArrayList) {
    row.add(0);
}
// 删除每一行的最后一列(如果行不为空)
for (ArrayList<Integer> row : twoDArrayList) {
    if (!row.isEmpty()) {
        row.remove(row.size() - 1);
    }
}

与传统二维数组 (int[][]) 的对比

特性 ArrayList<ArrayList<T>> T[][] (传统二维数组)
大小 动态,行和列的数量都可以随时改变。 固定,必须在创建时指定大小,之后不能改变。
内存 灵活,但可能有少量额外的开销(每个内部 ArrayList 对象的开销)。 连续的内存块,效率高,但浪费内存(如果某些行很短)。
性能 添加/删除元素非常快,随机访问比数组稍慢(因为涉及两次方法调用)。 随机访问极快(O(1)),大小固定,不灵活。
数据类型 可以存放任意对象类型(如 Integer, String)。 可以存放基本类型(int, char)或对象。
不规则性 天然支持“锯齿数组”(每行长度不同)。 不支持,所有行的长度必须相同。
  • 何时使用 ArrayList<ArrayList<T>>

    • 当你需要一个动态大小的二维结构时。
    • 当你的数据是不规则的(每行的列数不同)时。
    • 当你频繁需要添加或删除行/列时。
  • 何时使用传统二维数组 T[][]

    • 当你在编译时就知道确切的大小,并且它不会改变时。
    • 当你需要最高性能,尤其是在进行大量随机访问时。
    • 当处理基本类型数据(如 int, double)时,使用数组更节省内存(因为 ArrayList 只能存放对象)。
分享:
扫描分享到社交APP
上一篇
下一篇