Java List “加” List终极指南:从addAll()到Stream流,一篇搞定所有合并场景!
Meta描述:
还在为Java中如何合并两个List而烦恼?本文详细讲解addAll()、Collections.addAll()、Java 8 Stream流、循环遍历等多种List合并方法,附代码实例与性能对比,助你轻松掌握Java List加List技巧,解决开发难题!

引言:为什么我们需要合并List?
在Java开发中,List是我们最常用的集合类之一,无论是处理业务数据、API响应,还是简单的数据聚合,我们经常会遇到需要将两个或多个List合并成一个List的场景。
- 合并两个查询结果集。
- 聚合不同来源的用户列表。
- 将分页查询的数据合并成一份完整列表。
“Java list 加list”这个搜索词背后,是开发者对“合并”这一具体操作最直接、最朴素的需求,他们想知道“在Java里,如何把两个List拼在一起?”,本文将围绕这个核心问题,提供最全面、最实用的答案。
基础入门:最简单直接的合并方法——addAll()
对于初学者来说,List接口自带的addAll()方法是合并List最直观、最容易理解的方式。
使用目标List的addAll()方法
这是最常见的一种方式,将一个List中的所有元素追加到另一个List的末尾。

核心语法:
list1.addAll(list2);
代码示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListAddExample1 {
public static void main(String[] args) {
// 创建两个List
List<String> list1 = new ArrayList<>(Arrays.asList("Java", "Python", "C++"));
List<String> list2 = new ArrayList<>(Arrays.asList("Go", "Rust", "JavaScript"));
System.out.println("合并前 list1: " + list1);
System.out.println("合并前 list2: " + list2);
// 将list2的所有元素添加到list1中
list1.addAll(list2);
System.out.println("合并后 list1: " + list1);
System.out.println("合并后 list2: " + list2); // list2保持不变
}
}
执行结果:
合并前 list1: [Java, Python, C++]
合并前 list2: [Go, Rust, JavaScript]
合并后 list1: [Java, Python, C++, Go, Rust, JavaScript]
合并后 list2: [Go, Rust, JavaScript]
⚠️ 重要注意事项:

- 修改源List:此方法会直接修改
list1,list1本身成为了合并后的新列表,如果不想修改原始list1,你需要先创建一个它的副本。 - 元素引用:
addAll()操作是浅拷贝,如果List中存放的是对象(非基本类型),合并后的List中的元素与原始List中的元素指向的是同一个对象引用,修改其中一个List中的对象,会影响另一个。
修正版(不修改原始List):
// 创建一个新的List,包含list1的所有元素,然后再添加list2
List<String> mergedList = new ArrayList<>(list1); // 创建list1的副本
mergedList.addAll(list2);
System.out.println("原始 list1: " + list1);
System.out.println("合并后新List: " + mergedList);
使用Collections.addAll()
java.util.Collections工具类也提供了一个addAll()方法,但它接收一个目标Collection和一个可变数量的元素。
核心语法:
Collections.addAll(destinationList, sourceList.toArray());
代码示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class ListAddExample2 {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>(Arrays.asList("A", "B"));
List<String> list2 = new ArrayList<>(Arrays.asList("C", "D"));
// 创建一个新List来存储合并结果
List<String> mergedList = new ArrayList<>(list1);
// 将list2的所有元素添加到mergedList中
Collections.addAll(mergedList, list2.toArray(new String[0]));
System.out.println("合并后: " + mergedList);
}
}
这种方法与方法一类似,也需要手动处理原始List的拷贝问题。
进阶玩法:Java 8 Stream流式合并
如果你正在使用Java 8或更高版本,那么Stream API无疑是处理集合合并的“神器”,它代码更简洁,功能更强大,并且可以轻松实现去重、过滤等复杂操作。
使用Stream.concat()
Stream.concat()是专门用于合并两个流的静态方法,非常优雅。
核心语法:
List<T> 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 ListAddExample3 {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(3, 4, 5);
// 使用Stream.concat合并
List<Integer> mergedList = Stream.concat(list1.stream(), list2.stream())
.collect(Collectors.toList());
System.out.println("合并后: " + mergedList); // 输出: [1, 2, 3, 3, 4, 5]
}
}
Stream流合并的优势:
- 不可变性:此方法不会修改原始的
list1或list2,始终返回一个新的List,符合函数式编程思想,更安全。 - 链式操作:可以在合并后无缝衔接其他Stream操作,如
distinct()(去重)、filter()(过滤)、sorted()(排序)等。
进阶示例:合并并去重
List<Integer> mergedAndDistinctList = Stream.concat(list1.stream(), list2.stream())
.distinct() // 去重
.collect(Collectors.toList());
System.out.println("合并并去重后: " + mergedAndDistinctList); // 输出: [1, 2, 3, 4, 5]
性能与场景对比:我该用哪种方法?
没有最好的方法,只有最合适的方法,下面我们从几个维度进行对比:
| 方法 | 代码简洁性 | 是否修改原List | 功能扩展性 | 性能 | 推荐场景 |
|---|---|---|---|---|---|
list1.addAll(list2) |
中等 | 是(修改list1) | 弱 | 高 | 简单、直接的追加,且明确需要修改原List时。 |
Collections.addAll() |
中等 | 否(需手动拷贝) | 弱 | 高 | 与addAll类似,但需要将源List转为数组。 |
Stream.concat() |
高 | 否 | 极强 | 中等 | 推荐! Java 8+环境下的首选,尤其需要链式操作(去重、排序等)时。 |
循环遍历 for-each |
低 | 否(需手动拷贝) | 弱 | 低(但差异不大) | 不推荐,除非在循环中需要对每个元素进行特殊处理时。 |
性能小贴士:
对于超大规模的List(例如百万级数据),addAll()方法在底层优化上通常会比Stream.concat()有微弱的优势,因为它避免了流操作带来的额外开销,但在绝大多数业务场景下,这种性能差异可以忽略不计,代码的可读性和可维护性往往比那一点点性能提升更重要。
高级技巧:合并多个List
如果需要合并的不是一个,而是一组List,该怎么办?
使用Stream.of()与flatMap
当有多个List变量时,可以使用Stream.of()将它们包装成一个流,然后通过flatMap将每个List流“压平”成一个元素流。
代码示例:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MergeMultipleLists {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("A", "B");
List<String> list2 = Arrays.asList("C", "D");
List<String> list3 = Arrays.asList("E", "F");
// 使用Stream.of和flatMap合并多个List
List<String> allMerged = Stream.of(list1, list2, list3)
.flatMap(List::stream) // 将每个List转换为流,然后合并成一个流
.collect(Collectors.toList());
System.out.println("合并多个List后: " + allMerged); // 输出: [A, B, C, D, E, F]
}
}
使用List.addAll()循环
对于Java 8之前的版本,或者不习惯使用Stream的开发者,可以通过循环来实现。
代码示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MergeMultipleListsLegacy {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2);
List<Integer> list2 = Arrays.asList(3, 4);
List<Integer> list3 = Arrays.asList(5, 6);
List<Integer> allMerged = new ArrayList<>();
allMerged.addAll(list1);
allMerged.addAll(list2);
allMerged.addAll(list3);
System.out.println("合并多个List后: " + allMerged);
}
}
Java List合并的最佳实践
- 如果你使用的是Java 8+:强烈推荐使用
Stream.concat(),它不仅代码优雅,更重要的是它不改变原始数据,并且提供了无与伦比的扩展性,在需要去重、排序时,它能让你写出非常干净的业务逻辑。 - 如果你只需要简单追加,且不介意修改原List:
list1.addAll(list2)是一个高效且直接的选择,但请务必注意它会修改list1。 - 合并多个List:
Stream.of(...).flatMap(List::stream)是处理不定数量List合并的利器。 - 始终考虑不可变性:在大多数现代应用开发中,避免修改原始对象是一种良好的编程习惯,可以减少很多潜在的bug,即使使用
addAll(),也建议先拷贝再操作,或者直接使用Stream方案。
希望这篇“Java list 加list”终极指南能真正解决你的开发难题,从基础到高级,从原理到实践,我们已为你铺平了所有道路,选择最适合你当前场景的方法,写出更优雅、更健壮的Java代码吧!
