Java 实例 – 数组并集(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 Java 编程中,数组作为基础数据结构,经常需要进行合并、去重等操作。其中,“数组并集”是指将两个或多个数组中的元素合并为一个无重复的新数组。这一操作看似简单,但实现过程中会涉及算法效率、数据结构选择等核心知识点。本文将通过循序渐进的方式,结合代码示例和实际案例,深入讲解 Java 中数组并集的实现方法,并帮助读者理解其背后的逻辑原理。


数组并集的基础概念与应用场景

什么是数组并集?

数组并集(Array Union)是指将两个或多个数组中的元素合并成一个新数组,且新数组中不包含重复元素。例如,若数组 A = [1, 2, 3] 和数组 B = [3, 4, 5] 进行并集操作,结果应为 [1, 2, 3, 4, 5]

实际应用场景

数组并集在编程中常见于以下场景:

  • 数据合并:如电商系统需要合并不同来源的商品列表,去重后展示。
  • 数据清洗:合并多个日志文件中的记录,去除重复条目。
  • 算法优化:在算法竞赛或复杂逻辑中,快速合并多个数据集。

手动实现数组并集:基础方法与缺陷分析

基础实现思路

手动实现数组并集的核心步骤如下:

  1. 遍历源数组:逐个读取两个数组的所有元素。
  2. 去重操作:将元素存入临时存储空间(如 List),并通过检查是否已存在来避免重复。
  3. 转换为数组:将最终结果从临时存储转换为目标数组格式。

示例代码:手动实现

public static int[] arrayUnion(int[] arr1, int[] arr2) {  
    List<Integer> tempList = new ArrayList<>();  
    // 遍历第一个数组  
    for (int num : arr1) {  
        if (!tempList.contains(num)) {  
            tempList.add(num);  
        }  
    }  
    // 遍历第二个数组  
    for (int num : arr2) {  
        if (!tempList.contains(num)) {  
            tempList.add(num);  
        }  
    }  
    // 转换为数组  
    int[] result = new int[tempList.size()];  
    for (int i = 0; i < result.length; i++) {  
        result[i] = tempList.get(i);  
    }  
    return result;  
}  

方法缺陷分析

上述方法虽然简单易懂,但存在以下问题:

  1. 效率问题contains() 方法的时间复杂度为 O(n),导致整体时间复杂度为 O(n²),当数组规模较大时性能较差。
  2. 代码冗余:需要遍历两个数组并重复检查逻辑,扩展性差(例如合并三个数组时代码需大幅修改)。

借助集合类优化:使用 HashSetArrays 工具类

集合类的优势

Java 的 HashSet 是基于哈希表实现的集合,其 add() 方法的时间复杂度接近 O(1),能显著提升去重效率。结合 Arrays 工具类,可以简化代码逻辑。

示例代码:集合类实现

import java.util.Arrays;  
import java.util.HashSet;  
import java.util.List;  
import java.util.Set;  

public static int[] arrayUnionWithSet(int[] arr1, int[] arr2) {  
    // 将数组转换为 Set 去重  
    Set<Integer> set = new HashSet<>();  
    set.addAll(Arrays.stream(arr1).boxed().toList());  
    set.addAll(Arrays.stream(arr2).boxed().toList());  
    // 转换为数组  
    Integer[] tempArray = set.toArray(new Integer[0]);  
    // 强转为基本类型数组  
    int[] result = Arrays.stream(tempArray).mapToInt(Integer::intValue).toArray();  
    return result;  
}  

关键点解析

  1. 自动装箱与流式操作
    • Arrays.stream(arr1).boxed() 将基本类型数组转换为 IntStream,再通过 boxed() 转为 Stream<Integer>
    • toList() 方法将流转换为 List,便于 addAll() 操作。
  2. 数组类型转换
    • Set 转为 Integer[] 后,通过 mapToInt 将包装类型转为基本类型 int[]

进阶优化:时间复杂度与空间复杂度的权衡

算法复杂度分析

方法时间复杂度空间复杂度
手动遍历(基础方法)O(n²)O(n)
集合类优化方法O(n)O(n)

优化策略总结

  1. 优先选择集合类:对于中大型数据集,HashSet 的 O(n) 复杂度是更优选择。
  2. 避免重复遍历:通过流式操作一次性处理多个数组。
  3. 类型适配:根据需求选择基本类型数组或对象数组,避免不必要的装箱操作。

实际案例:电商商品合并场景

案例背景

某电商平台需要合并两个商品库的 ID 列表,确保最终结果无重复且顺序无关紧要。

数据准备

// 商品库 A 的 ID 列表  
int[] productIdsA = {1001, 1002, 1003, 1004};  
// 商品库 B 的 ID 列表  
int[] productIdsB = {1003, 1004, 1005, 1006};  

调用优化方法

int[] mergedIds = arrayUnionWithSet(productIdsA, productIdsB);  
System.out.println("合并后的商品 ID 数组:" + Arrays.toString(mergedIds));  

输出结果

合并后的商品 ID 数组:[1001, 1002, 1003, 1004, 1005, 1006]

案例总结

通过集合类方法,代码简洁且性能高效,完美适配实际业务需求。


常见问题与解决技巧

问题 1:合并多个数组时如何扩展代码?

解答
使用可变参数和循环遍历所有数组:

public static int[] arrayUnionWithSet(int[]... arrays) {  
    Set<Integer> set = new HashSet<>();  
    for (int[] arr : arrays) {  
        set.addAll(Arrays.stream(arr).boxed().toList());  
    }  
    // 后续转换逻辑与之前相同  
    return ...;  
}  

问题 2:如何保持合并后的数组元素顺序?

解答
若需保留原始顺序,可改用 LinkedHashSet 替代 HashSet,它能维护插入顺序。


结论

通过本文的讲解,读者可以掌握 Java 中数组并集的两种实现方法:基础的手动遍历法和高效的集合类法。对于编程初学者,建议先理解手动实现的逻辑,再逐步过渡到集合类的优化方案;对于中级开发者,则需关注算法复杂度分析和实际场景适配。

在开发过程中,合理选择数据结构(如 HashSet)和工具类(如 Arrays)是提升代码质量的关键。未来,随着项目需求的复杂化,读者还可进一步探索多线程并行处理或分布式计算的优化方案,但万变不离其宗,扎实的数组操作基础是进阶的前提。

最新发布