1. 概述
在本篇文章中,我们来探讨如何计算两个整数数组 a
和 b
的交集。
同时,我们也会关注如何处理数组中的重复元素问题。
为了实现这个功能,我们会使用 Java 8 的 Stream API 来简化操作。
2. 判断元素是否属于另一个数组
根据集合论的定义,两个集合的交集是由那些既出现在第一个集合中、也出现在第二个集合中的元素组成的。
因此我们需要一个 Predicate(谓词)来判断某个元素是否存在于第二个数组中。由于 List
提供了 contains
方法,我们可以将数组转换为 List
后直接使用:
Predicate isContainedInB = Arrays.asList(b)::contains;
✅ 这种方式简单粗暴,适合快速判断元素是否在目标数组中。
3. 构建交集数组
要构建交集结果,我们可以依次遍历第一个数组中的每个元素,并筛选出那些也存在于第二个数组中的元素。最后将这些元素收集到一个新的数组中。
利用 Stream API,整个流程可以非常简洁地表达:
public static Integer[] intersectionSimple(Integer[] a, Integer[] b){
return Stream.of(a)
.filter(Arrays.asList(b)::contains)
.toArray(Integer[]::new);
}
⚠️ 注意:这种方式保留了第一个数组中的重复元素,也就是说,如果 a
中某元素出现多次且也在 b
中,则结果中也会出现多次。
4. 处理重复元素
Java 中的数组不是 Set 类型,所以天然支持重复元素。这就带来一个问题:交集中是否应该去重?
对于标准集合(Set),每个元素只能出现一次。我们可以通过 .distinct()
方法来实现去重逻辑:
public static Integer[] intersectionSet(Integer[] a, Integer[] b){
return Stream.of(a)
.filter(Arrays.asList(b)::contains) // ⚠️ 原文拼写错误,应为 contains
.distinct()
.toArray(Integer[]::new);
}
✅ 使用 distinct()
后,交集长度不再依赖于参数顺序,更符合集合语义。
❌ 但需要注意的是,此时一个数组与自身的交集可能不再是原数组本身(因为去重了)。
5. 多重集(Multiset)交集
如果我们允许交集中存在重复元素,并且希望结果中每个元素的出现次数等于其在两个数组中最小的出现次数,那么这就是所谓的“多重集交集”。
在这种情况下,我们需要一种机制来记录某个元素已经被匹配过。可以借助 List.remove()
方法实现这一点:
public static Integer[] intersectionMultiset(Integer[] a, Integer[] b){
return Stream.of(a)
.filter(new LinkedList<>(Arrays.asList(b))::remove)
.toArray(Integer[]::new);
}
💡 remove()
方法不仅会判断元素是否存在,还会将其从列表中移除,从而避免重复匹配。
⚠️ 因为 Arrays.asList()
返回的是不可变列表,所以我们需要用 LinkedList
包装一层以获得可变性。
6. 总结
在这篇文章中,我们展示了如何通过 contains
和 remove
方法结合 Stream API 实现两个整数数组的多种交集计算方式:
- 简单交集(保留重复)
- 集合交集(去重)
- 多重集交集(按最小频次保留)
所有示例代码和测试用例都可以在我们的 GitHub 仓库 中找到。这是一个基于 Maven 的项目,导入即可运行。