| 方法 | 代码示例 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
使用 Arrays.asList() |
List<String> list = Arrays.asList(arr); |
最简单、最直接,性能高 | 返回的是固定长度的 ArrayList,不能增删 |
当你只需要一个 List 来读取数组元素时 |
| 使用 Java 8 Stream | List<String> list = Arrays.stream(arr).collect(Collectors.toList()); |
灵活,可链式操作,返回真正可变的 ArrayList |
代码稍长,对于简单转换略显繁琐 | 需要对数组元素进行过滤、映射等操作,或需要一个可变列表 |
| 使用 Collections.addAll() | List<String> list = new ArrayList<>(); Collections.addAll(list, arr); |
返回真正可变的 ArrayList,性能也很好 |
需要先创建一个空的 ArrayList 对象 |
当你明确需要一个可变列表,并且不想使用 Stream 时 |
使用 Arrays.asList() (最常用)
这是最直接、最简单的方法,但它有一个非常重要的“陷阱”。
代码示例
import java.util.Arrays;
import java.util.List;
public class ArrayToListExample {
public static void main(String[] args) {
// 1. 定义一个 String 数组
String[] stringArray = {"Apple", "Banana", "Orange"};
// 2. 使用 Arrays.asList() 将数组转换为 List
// 注意:这里得到的 List 是 java.util.Arrays.ArrayList,它是一个内部类
List<String> fruitList = Arrays.asList(stringArray);
System.out.println("转换后的 List: " + fruitList);
System.out.println("List 的第一个元素: " + fruitList.get(0));
// --- 重要的警告 ---
System.out.println("\n--- 尝试修改 List ---");
// 修改 List 中的元素(可以修改)
fruitList.set(0, "Grape");
System.out.println("修改 List 后的数组: " + Arrays.toString(stringArray)); // 数组也被修改了!
System.out.println("修改 List 后的 List: " + fruitList);
// 尝试向 List 中添加新元素(会抛出异常)
try {
fruitList.add("Mango");
System.out.println("添加元素成功: " + fruitList);
} catch (UnsupportedOperationException e) {
System.out.println("错误: 不能向由 Arrays.asList() 创建的 List 中添加元素!");
}
// 尝试从 List 中删除元素(同样会抛出异常)
try {
fruitList.remove(0);
System.out.println("删除元素成功: " + fruitList);
} catch (UnsupportedOperationException e) {
System.out.println("错误: 不能从由 Arrays.asList() 创建的 List 中删除元素!");
}
}
}
关键点解析
- 返回类型:
Arrays.asList()返回的List并不是我们平时常用的java.util.ArrayList,它是一个固定长度(fixed-size)的列表,是Arrays类的一个内部类。 - 视图而非副本:这个
List是原始数组的视图,这意味着你对List的任何修改(set())都会直接反映到原始数组上,反之亦然。 - 不可增删:由于它是固定长度的,所以你不能使用
add()或remove()方法来改变其大小,否则会抛出UnsupportedOperationException。
适用场景
当你只需要遍历数组,或者基于数组创建一个只读的 List 视图时,这个方法非常高效。
使用 Java 8 Stream API (最灵活)
如果你需要一个真正可以修改大小的 ArrayList,或者想在转换过程中进行一些操作,Stream API 是最佳选择。
代码示例
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamExample {
public static void main(String[] args) {
// 1. 定义一个 Integer 数组
Integer[] intArray = {1, 2, 3, 4, 5};
// 2. 使用 Stream API 转换
List<Integer> numberList = Arrays.stream(intArray) // 1. 创建一个流
.collect(Collectors.toList()); // 2. 将流收集到新的 List 中
System.out.println("转换后的 List: " + numberList);
// --- 优势:可以轻松进行链式操作 ---
List<Integer> evenNumbers = Arrays.stream(intArray)
.filter(n -> n % 2 == 0) // 过滤出偶数
.collect(Collectors.toList());
System.out.println("过滤后的偶数 List: " + evenNumbers);
// --- 优势:返回的是真正的可变 ArrayList ---
numberList.add(6); // 可以添加
numberList.remove(0); // 可以删除
System.out.println("修改后的 List: " + numberList);
}
}
关键点解析
Arrays.stream(arr):将数组转换为Stream。.collect(Collectors.toList()):这是流的终端操作,它将流中的元素收集到一个新的List中,这个List默认就是java.util.ArrayList,是完全可变的。- 灵活性:在
collect之前,你可以进行各种中间操作,如filter()(过滤)、map()(转换)、sorted()(排序)等。
适用场景
当你需要一个可变的 ArrayList,或者想在转换数组的同时对元素进行处理时,这是现代 Java 中最推荐的方法。
使用 Collections.addAll() (传统方法)
这是一种比较传统但有效的方法,同样可以得到一个可变的 ArrayList。
代码示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CollectionsAddAllExample {
public static void main(String[] args) {
// 1. 定义一个 String 数组
String[] stringArray = {"Cat", "Dog", "Bird"};
// 2. 创建一个新的空的 ArrayList
List<String> animalList = new ArrayList<>();
// 3. 使用 Collections.addAll() 将数组所有元素添加到 List 中
Collections.addAll(animalList, stringArray);
System.out.println("转换后的 List: " + animalList);
// --- 这是一个真正的可变 ArrayList ---
animalList.add("Fish");
animalList.remove("Cat");
System.out.println("修改后的 List: " + animalList);
}
}
关键点解析
- 需要预先创建
List:你必须先创建一个空的ArrayList实例。 - 性能好:
Collections.addAll()方法在内部使用高效的System.arraycopy,性能很高。 - 返回可变列表:最终得到的
animalList是一个标准的、可修改的ArrayList。
适用场景
在不使用 Stream API 的旧代码中,或者当你明确想分步骤(先创建列表,再填充内容)时,这是一个很好的选择。
总结与最佳实践
| 特性 | Arrays.asList() |
Stream API (Collectors.toList()) |
Collections.addAll() |
|---|---|---|---|
| 是否可变 | 否 (固定大小) | 是 (标准 ArrayList) |
是 (标准 ArrayList) |
| 代码简洁性 | 最高 | 中等 | 中等 |
| 灵活性 | 低 (仅视图) | 最高 (可链式操作) | 低 (仅添加) |
| 性能 | 最高 (直接包装) | 较好 (有流操作开销) | 高 (底层是 arraycopy) |
如何选择?
-
只需要读取数据:如果你的唯一目的就是遍历数组或者把它当作一个只读的集合传递给方法,使用
Arrays.asList(),它最快、最简单。 -
需要一个可修改的列表:如果你需要向结果列表中添加或删除元素,请避免使用
Arrays.asList()。- 推荐使用 Stream API:
Arrays.stream(arr).collect(Collectors.toList()),这是现代 Java 的标准做法,不仅功能强大,而且代码意图清晰。 - 备选方案: 如果项目不能使用 Java 8+,或者你不喜欢 Stream 的写法,可以使用
Collections.addAll()。
- 推荐使用 Stream API:
-
转换时需要处理数据:如果你想在转换数组的同时过滤、排序或转换元素,Stream API 是唯一的选择。
int[] nums = {1, 2, 3, 4, 5}; List<Integer> squaredEvens = Arrays.stream(nums) .filter(n -> n % 2 == 0) .map(n -> n * n) .boxed() // int -> Integer .collect(Collectors.toList()); // 结果是 [4, 16]
