Java 实例 – 数组并集:从零开始掌握集合运算
在日常开发中,我们经常需要处理多个数据集合之间的关系。比如,两个用户列表合并去重、两个商品分类合并展示、两个日志时间段合并分析等。这些场景背后,其实都涉及“并集”这个基础数学概念。今天我们就来深入聊聊 Java 实例 – 数组并集 的实现方式,帮助你从基础到进阶,掌握这个实用技能。
并集,简单来说就是两个集合中所有不重复元素的合并结果。比如集合 A = {1, 2, 3},集合 B = {3, 4, 5},那么它们的并集就是 {1, 2, 3, 4, 5}。注意,重复元素只保留一份。
在 Java 中,数组是基础数据结构,但不像集合类那样自带并集操作。因此我们需要手动实现。接下来,我们就一步步来。
什么是数组并集?通俗理解
想象你有两个朋友,分别整理了他们喜欢的电影列表:
- 小明:《肖申克的救赎》《盗梦空间》《阿甘正传》
- 小红:《盗梦空间》《星际穿越》《阿甘正传》《泰坦尼克号》
现在你想知道他们俩都喜欢哪些电影,不管谁先列的,只要出现过就算。这就是“并集”——把两个列表合并,去重后展示。
在 Java 中,我们用数组来表示这些电影名字,然后通过代码实现“合并去重”。这正是我们要掌握的核心技能。
创建数组与初始化
首先,我们得有数据。Java 中数组是固定长度的容器,适合存储同类型数据。我们用字符串数组来表示电影名。
// 定义小明喜欢的电影列表
String[] moviesXiaoMing = {"肖申克的救赎", "盗梦空间", "阿甘正传"};
// 定义小红喜欢的电影列表
String[] moviesXiaoHong = {"盗梦空间", "星际穿越", "阿甘正传", "泰坦尼克号"};
这里要注意,数组的长度在创建后不能改变。所以如果未来想动态添加元素,建议使用 ArrayList,但我们今天先聚焦数组,因为这是“Java 实例 – 数组并集”的核心前提。
实现并集的三种主流方法
方法一:使用 Set 去重(推荐)
Set 是 Java 集合框架中一个非常重要的接口,它的核心特性就是“自动去重”。我们可以通过将数组转换为 Set,再合并,最后转回数组。
import java.util.*;
public class ArrayUnion {
public static void main(String[] args) {
// 原始数据
String[] moviesXiaoMing = {"肖申克的救赎", "盗梦空间", "阿甘正传"};
String[] moviesXiaoHong = {"盗梦空间", "星际穿越", "阿甘正传", "泰坦尼克号"};
// 第一步:将两个数组转换为 Set,自动去重
Set<String> set1 = new HashSet<>(Arrays.asList(moviesXiaoMing));
Set<String> set2 = new HashSet<>(Arrays.asList(moviesXiaoHong));
// 第二步:合并两个 Set,使用 addAll 方法
set1.addAll(set2);
// 第三步:将合并后的 Set 转换为数组
String[] unionMovies = set1.toArray(new String[0]);
// 输出结果
System.out.println("合并后的电影列表(并集):");
for (String movie : unionMovies) {
System.out.println(movie);
}
}
}
代码说明:
Arrays.asList():将数组转为 List,便于后续操作。new HashSet<>(...):创建一个 HashSet,自动去重。addAll():将一个集合的所有元素添加到另一个集合中。toArray(new String[0]):将 Set 转为字符串数组,参数new String[0]是类型提示,避免泛型擦除问题。
✅ 这种方法最简洁高效,适合大多数场景,是 Java 实例 – 数组并集 的首选方案。
方法二:手动遍历 + 判断去重
如果你不想用集合类,也可以手动实现。这有助于理解并集的本质。
public class ArrayUnionManual {
public static void main(String[] args) {
String[] moviesXiaoMing = {"肖申克的救赎", "盗梦空间", "阿甘正传"};
String[] moviesXiaoHong = {"盗梦空间", "星际穿越", "阿甘正传", "泰坦尼克号"};
// 创建结果数组,初始长度为两个数组之和
List<String> result = new ArrayList<>();
// 遍历第一个数组
for (String movie : moviesXiaoMing) {
result.add(movie); // 直接添加,因为是第一个
}
// 遍历第二个数组,判断是否已存在
for (String movie : moviesXiaoHong) {
boolean exists = false;
for (String item : result) {
if (item.equals(movie)) {
exists = true;
break; // 找到就跳出内层循环
}
}
if (!exists) {
result.add(movie); // 不存在才添加
}
}
// 转为数组输出
String[] unionMovies = result.toArray(new String[0]);
System.out.println("手动实现的并集结果:");
for (String movie : unionMovies) {
System.out.println(movie);
}
}
}
代码说明:
- 使用
ArrayList作为临时容器,因为它可以动态扩容。 - 外层循环处理第一个数组,直接加入。
- 内层循环检查第二个数组中的每个元素是否已在结果中。
equals()方法用于字符串比较,比==更安全。- 时间复杂度为 O(n×m),适合小数据量。
⚠️ 优点是逻辑清晰,适合学习;缺点是性能较差,不推荐在大数据量时使用。
方法三:使用 Java 8 Stream API(现代写法)
Java 8 引入了 Stream API,让集合操作变得非常简洁。我们也可以用它来实现并集。
import java.util.*;
import java.util.stream.Collectors;
public class ArrayUnionStream {
public static void main(String[] args) {
String[] moviesXiaoMing = {"肖申克的救赎", "盗梦空间", "阿甘正传"};
String[] moviesXiaoHong = {"盗梦空间", "星际穿越", "阿甘正传", "泰坦尼克号"};
// 使用 Stream 合并并去重
List<String> unionMovies = Arrays.stream(moviesXiaoMing)
.distinct() // 去重(可选,防止第一个数组重复)
.collect(Collectors.toList())
.stream()
.distinct() // 再次去重
.collect(Collectors.toList());
// 将第二个数组合并进来
unionMovies.addAll(
Arrays.stream(moviesXiaoHong)
.distinct()
.collect(Collectors.toList())
);
// 最终去重并转为数组
String[] result = unionMovies.stream()
.distinct()
.toArray(String[]::new);
System.out.println("Stream API 实现的并集:");
Arrays.stream(result).forEach(System.out::println);
}
}
代码说明:
Arrays.stream():将数组转为 Stream。distinct():去除重复元素。Collectors.toList():将 Stream 转为 List。toArray(String[]::new):将 List 转为数组,使用构造器引用。
✅ 这种写法现代、优雅,适合在项目中使用。虽然代码稍长,但可读性高。
性能对比与选择建议
| 方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| Set 去重 | O(n + m) | O(n + m) | 快速、简洁、推荐 | 需要额外集合类 |
| 手动遍历 | O(n×m) | O(n + m) | 逻辑清晰,无依赖 | 性能差,不适合大数据 |
| Stream API | O(n + m) | O(n + m) | 代码优雅,适合函数式编程 | 学习成本略高 |
建议:
- 日常开发中,优先使用 Set 去重法,它是 Java 实例 – 数组并集 的最佳实践。
- 学习阶段可以尝试手动实现,加深理解。
- 项目中若已使用 Stream,可考虑 Stream 方案。
实际应用场景举例
- 用户权限合并:两个角色的权限列表合并,去重后生成最终权限。
- 日志时间范围合并:多个时间段可能有重叠,合并后形成连续区间。
- 商品分类合并:两个分类下的商品 ID 合并,去重后展示。
- 数据清洗:从多个来源获取数据,合并去重,避免重复处理。
这些场景都离不开“并集”运算。掌握 Java 实例 – 数组并集,意味着你具备了处理真实业务数据的基本能力。
常见误区与注意事项
- ❌ 不要用
==比较字符串:应使用equals()。 - ❌ 不要直接用
set.toArray()无参:可能导致类型错误,应传入new String[0]。 - ❌ 不要忽略数组长度:如果数组很大,手动遍历可能超时。
- ✅ 始终考虑去重逻辑:并集的核心就是“不重复”。
总结
今天我们深入探讨了 Java 实例 – 数组并集 的多种实现方式。从最基础的数组定义,到 Set 去重、手动遍历、Stream API,每一种方法都有其适用场景。
- 对初学者:推荐从手动实现入手,理解并集的原理。
- 对中级开发者:应掌握 Set 方案,它是高效、稳定的首选。
- 对高级开发者:可结合 Stream API,写出更现代、可读性更强的代码。
记住,编程不是记住代码,而是理解逻辑。当你能用不同方式解决同一个问题时,你才算真正掌握了它。
希望今天的分享能帮你打通“数组并集”这道关卡。下次遇到数据合并问题,别再手忙脚乱,拿出你的工具箱,优雅地解决问题。