Java 常见合并集合几种方式总结(List、Set、Map)
Java 提供了多种方式来合并集合(List、Set、Map),不同场景下可选择最合适的方法。以下是常见的合并集合方式的整理:
1. 合并 List
1.1 addAll()
- 适用场景:直接合并两个 List
- 特点:修改原集合,无需创建新集合
- 示例:
List list1 = new ArrayList<>(Arrays.asList("A", "B", "C"));
List list2 = Arrays.asList("D", "E");
list1.addAll(list2);
System.out.println(list1); // [A, B, C, D, E]
1.2 Stream.concat()
- 适用场景:不修改原集合,返回新 List
- 特点:流式操作,适用于不可变集合
- 示例:
List mergedList = Stream.concat(list1.stream(), list2.stream())
.collect(Collectors.toList());
System.out.println(mergedList); // [A, B, C, D, E]
1.3 Stream.of() + flatMap()
- 适用场景:合并多个 List
- 特点:可同时合并多个 List
- 示例:
List list3 = Arrays.asList("F", "G");
List mergedList = Stream.of(list1, list2, list3)
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(mergedList); // [A, B, C, D, E, F, G]
1.4 List.copyOf()
- 适用场景:创建不可变 List
- 特点:返回 不可变 集合
- 示例:
List mergedList = List.copyOf(Stream.concat(list1.stream(), list2.stream())
.collect(Collectors.toList()));
System.out.println(mergedList); // [A, B, C, D, E]
2. 合并 Set
2.1 addAll()
- 适用场景:合并 Set(无重复元素)
- 示例:
Set set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set set2 = new HashSet<>(Arrays.asList(3, 4, 5));
set1.addAll(set2);
System.out.println(set1); // [1, 2, 3, 4, 5]
2.2 Stream.concat()
- 适用场景:不修改原集合
- 示例:
Set mergedSet = Stream.concat(set1.stream(), set2.stream())
.collect(Collectors.toSet());
System.out.println(mergedSet); // [1, 2, 3, 4, 5]
2.3 Stream.of() + flatMap()
- 适用场景:合并多个 Set
- 示例:
Set set3 = new HashSet<>(Arrays.asList(6, 7));
Set mergedSet = Stream.of(set1, set2, set3)
.flatMap(Set::stream)
.collect(Collectors.toSet());
System.out.println(mergedSet); // [1, 2, 3, 4, 5, 6, 7]
3. 合并 Map
3.1 putAll()
- 适用场景:直接合并 Map
- 特点:如果 key 存在,后者会覆盖前者
- 示例:
Map map1 = new HashMap<>();
map1.put("A", 1);
map1.put("B", 2);
Map map2 = new HashMap<>();
map2.put("B", 3);
map2.put("C", 4);
map1.putAll(map2);
System.out.println(map1); // {A=1, B=3, C=4}
3.2 merge()
- 适用场景:合并时处理重复 key
- 特点:可指定 key 处理方式
- 示例:
map2.forEach((key, value) ->
map1.merge(key, value, Integer::sum)
);
System.out.println(map1); // {A=1, B=5, C=4}
3.3 compute()
- 适用场景:动态计算 key
- 示例:
map2.forEach((key, value) ->
map1.compute(key, (k, v) -> (v == null) ? value : v + value)
);
System.out.println(map1); // {A=1, B=5, C=4}
3.4 Stream API
- 适用场景:不修改原 Map,生成新 Map
- 示例:
Map mergedMap = Stream.of(map1, map2)
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
Integer::sum));
System.out.println(mergedMap); // {A=1, B=5, C=4}
4. 总结
数据结构 | 方法 | 适用场景 | 是否修改原集合 |
---|---|---|---|
List | addAll() | 直接合并 | ✅ |
Stream.concat() | 不修改原 List | ❌ | |
Stream.of() + flatMap() | 合并多个 List | ❌ | |
List.copyOf() | 创建不可变 List | ❌ | |
Set | addAll() | 直接合并 | ✅ |
Stream.concat() | 不修改原 Set | ❌ | |
Stream.of() + flatMap() | 合并多个 Set | ❌ | |
Map | putAll() | 后者覆盖前者 | ✅ |
merge() | 合并相同 key | ✅ | |
compute() | 计算 key 值 | ✅ | |
Stream API | 不修改原 Map | ❌ |
- ✅ 修改原集合:适用于直接更新已有集合的场景。
- ❌ 不修改原集合:适用于函数式编程、不可变集合的场景。
这几种方式适用于不同的开发需求,具体选择哪种方法取决于业务逻辑和性能要求。