在 Java 中,将一个 List 添加到另一个 List 中,有几种常见的方法,下面我将详细介绍这些方法,并提供代码示例和各自的优缺点。
核心方法概览
| 方法 | 描述 | 是否修改原列表 | 是否创建新列表 | 适用场景 |
|---|---|---|---|---|
addAll(Collection<? extends E> c) |
将指定集合中的所有元素追加到列表的末尾。 | 是 | 否 | 最常用、最高效的方式。 |
Java 8+ Stream |
使用流式操作来合并列表,功能强大且灵活。 | 否 (可链式操作) | 是 | 需要对合并后的列表进行进一步处理时。 |
循环 + add() |
遍历源列表,逐个将元素添加到目标列表。 | 是 | 否 | 逻辑简单,但代码冗长,不推荐。 |
| 构造函数 | 创建一个新列表,其初始元素包含指定集合的元素。 | 否 | 是 | 当你需要一个全新的、合并后的列表,且不希望修改任何原始列表时。 |
addAll() - 最推荐
这是最直接、最常用且性能最高的方法,它会直接将源列表的所有元素追加到目标列表的末尾。
语法:
list1.addAll(list2);
示例代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AddListToListExample {
public static void main(String[] args) {
// 创建两个初始列表
List<String> list1 = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> list2 = new ArrayList<>(Arrays.asList("D", "E", "F"));
System.out.println("合并前 list1: " + list1);
System.out.println("合并前 list2: " + list2);
// 使用 addAll() 将 list2 的所有元素添加到 list1 的末尾
list1.addAll(list2);
System.out.println("合并后 list1: " + list1);
System.out.println("合并后 list2: " + list2); // list2 保持不变
}
}
输出:
合并前 list1: [A, B, C]
合并前 list2: [D, E, F]
合并后 list1: [A, B, C, D, E, F]
合并后 list2: [D, E, F]
优点:
- 简洁: 一行代码即可完成操作。
- 高效: 底层实现是优化过的,通常比循环逐个添加更快。
- 意图明确: 代码清晰地表达了“将一个列表的内容追加到另一个列表”的意图。
注意:
- 此方法会修改
list1。 list2中的元素会被浅拷贝到list1,如果列表中的元素是对象(而不是基本类型),那么两个列表将引用同一个对象,修改其中一个列表中的对象会影响另一个。
Java 8+ Stream API - 最灵活
如果你使用的是 Java 8 或更高版本,可以使用 Stream API 来合并列表,这种方法非常灵活,尤其是在合并后需要对结果进行进一步处理(如过滤、排序、映射)时。
语法:
List<E> mergedList = Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());
示例代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamAddListToListExample {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Integer> list2 = new ArrayList<>(Arrays.asList(4, 5, 6));
// 使用 Stream.concat 合并两个流,然后收集到一个新的 List 中
List<Integer> mergedList = Stream.concat(list1.stream(), list2.stream())
.collect(Collectors.toList());
System.out.println("原始 list1: " + list1);
System.out.println("原始 list2: " + list2);
System.out.println("合并后的新列表: " + mergedList);
}
}
输出:
原始 list1: [1, 2, 3]
原始 list2: [4, 5, 6]
合并后的新列表: [1, 2, 3, 4, 5, 6]
优点:
- 不可变性: 不会修改原始的
list1或list2,而是创建了一个全新的mergedList。 - 功能强大: 可以轻松地在合并后进行链式操作,
// 合并并过滤掉偶数 List<Integer> filteredList = Stream.concat(list1.stream(), list2.stream()) .filter(n -> n % 2 != 0) .collect(Collectors.toList()); System.out.println("合并并过滤后的列表: " + filteredList); // 输出: [1, 3, 5] - 并行处理: 可以轻松地切换为并行流
.parallelStream()来处理大数据量。
循环 + add() - 不推荐
这是一种基础的方法,通过 for-each 循环遍历源列表,并使用 add() 方法将每个元素添加到目标列表。
示例代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LoopAddListToListExample {
public static void main(String[] args) {
List<Double> list1 = new ArrayList<>(Arrays.asList(1.1, 2.2, 3.3));
List<Double> list2 = new ArrayList<>(Arrays.asList(4.4, 5.5, 6.6));
System.out.println("合并前 list1: " + list1);
// 遍历 list2 并逐个添加到 list1
for (Double number : list2) {
list1.add(number);
}
System.out.println("合并后 list1: " + list1);
}
}
缺点:
- 代码冗长: 相比
addAll(),需要更多的代码。 - 性能稍差: 虽然现代 JVM 优化得很好,但
addAll()的内部实现通常更优。 - 可读性差: 不如
addAll()那么直接明了。
什么时候可能用?
当你在循环中需要对源列表的每个元素进行一些处理或判断后再添加时,这种方法才有意义,但如果仅仅是添加,addAll() 是更好的选择。
构造函数 - 创建新列表
如果你不希望修改任何一个原始列表,而是希望得到一个全新的、包含两个列表所有元素的新列表,可以使用 ArrayList 的构造函数。
语法:
List<E> mergedList = new ArrayList<>(list1); // 先创建一个包含list1所有元素的新列表
mergedList.addAll(list2); // 再将list2的元素添加进去
或者更简洁的写法(Java 9+):
List<E> mergedList = new ArrayList<>(list1); mergedList.addAll(list2);
示例代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ConstructorAddListToListExample {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>(Arrays.asList("Apple", "Banana"));
List<String> list2 = new ArrayList<>(Arrays.asList("Cherry", "Date"));
// 1. 创建一个基于 list1 的新列表
List<String> mergedList = new ArrayList<>(list1);
// 2. 将 list2 的所有元素添加到这个新列表中
mergedList.addAll(list2);
System.out.println("原始 list1: " + list1);
System.out.println("原始 list2: " + list2);
System.out.println("创建的新合并列表: " + mergedList);
}
}
输出:
原始 list1: [Apple, Banana]
原始 list2: [Cherry, Date]
创建的新合并列表: [Apple, Banana, Cherry, Date]
优点:
- 不可变性: 完全不修改原始的
list1和list2。 - 结果清晰: 得到的
mergedList是一个全新的独立列表。
总结与选择建议
| 你的需求 | 推荐方法 |
|---|---|
| 想快速、高效地将一个列表追加到另一个列表的末尾,并允许修改原列表。 | list1.addAll(list2); (首选) |
| 想合并两个列表,但不希望修改任何一个原始列表,并可能需要对结果进行后续处理(如过滤、排序)。 | Stream.concat() (Java 8+) |
| 想创建一个全新的独立列表,包含两个原始列表的所有内容,且不修改任何原始列表。 | 构造函数 + addAll() |
| (不推荐)只是想了解基本原理,或者在循环中需要添加前对元素进行复杂处理。 | for-each 循环 + add() |
对于绝大多数日常开发场景,addAll() 是最简单、最直接、最合适的选择,如果你需要函数式编程的优雅和不可变性,Stream.concat() 则是绝佳的选择。
