讲师中心 微信公众号
AI工具推荐 视频效率加速

在Java中如何使用distinct去除集合中的重复元素_Java去重操作解析

胖宇小哥_7128

胖宇小哥_7128

发布时间:2026-02-04 09:48:08

|

529人浏览过

|

来源于php中文网

原创

distinct()严格依赖equals()和hashCode()的正确实现;自定义类必须重写二者,否则字段相同也被视为不同;按字段去重需filter+ConcurrentHashMap;去重逻辑须匹配业务语义。

在java中如何使用distinct去除集合中的重复元素_java去重操作解析

Java 8 Stream.distinct() 的适用前提和限制

distinct() 方法本身不依赖元素的业务逻辑,但它**严格依赖 equals() 和 hashCode() 的正确实现**。如果自定义对象没重写这两个方法,哪怕两个对象字段完全相同,distinct() 也会把它们视为不同元素。

常见错误现象:Stream.of(new User("Alice", 25), new User("Alice", 25)).distinct().count() 返回 2 —— 因为默认使用 Object 的 hashCode(),地址不同即不同。

  • 对 String、Integer 等 JDK 内置类型可直接用 distinct()
  • 对自定义类,必须确保 equals()/hashCode() 覆盖了所有参与“相等判断”的字段
  • 注意:distinct() 是有状态操作,不能并行流中随意替换为无状态替代方案

按对象某个字段去重(比如 name 去重保留第一个)

标准 distinct() 不支持“按字段去重”,它只认整个对象是否重复。要实现“按 name 去重”,本质是需要一个“已见 name 集合”做状态记录。

推荐写法(线程安全、语义清晰):

Java调试
Java调试

通过 JDWP 实现 Java 远程调试:连接远程 JVM、设置断点、单步执行代码、查看变量值、获取调用栈。适用于需要调试远程 Java 应用、排查运行时状态、追踪代码执行流程的场景。 术语注解 JDWP:Java Debug Wire Protocol,Java 调试有线协议(Java 远程调试底层通信协议) remote JVM:远程 Java 虚拟机 step through code:代码单步调试(步入 / 步过 / 步出调试) inspect variables:变量查看 / 变量检视 stac

下载

立即学习“Java免费学习笔记(深入)”;

Set<String> seen = ConcurrentHashMap.newKeySet();
list.stream()
    .filter(user -> seen.add(user.getName()))
    .collect(Collectors.toList());
  • 用 ConcurrentHashMap.newKeySet() 而非 HashSet,避免并行流下 add() 竞态
  • seen.add(x) 返回 true 表示首次加入,正好作为 filter 条件
  • 不建议用 Collectors.toMap() + Function.identity(),容易因重复 key 抛 IllegalStateException

distinct() 在 List、Set、Map 转换中的性能差异

distinct() 本身内部用的是 LinkedHashSet 缓存已见元素,所以时间复杂度是 O(n),但会额外占用 O(n) 空间。实际效果受上游数据结构影响很大:

  • 从 ArrayList 流式去重:典型场景,无额外开销
  • 从已有 HashSet 开始流:此时再调 distinct() 完全冗余,纯属浪费 CPU 和内存
  • 从数据库查出的 List<map object>></map>:每个 Map 默认无合理 equals(),distinct() 几乎无效,应先转成确定类型的对象再处理

替代方案:用 TreeSet 自定义去重逻辑(适合排序+去重)

如果既要按某字段去重,又希望结果有序(比如按 id 升序),TreeSet 比 “filter + Set 记录” 更简洁:

Set<User> unique = list.stream()
    .collect(Collectors.toCollection(
        () -> new TreeSet<>(Comparator.comparing(User::getName))
    ));
  • 注意:这会丢弃原始顺序;若需保持首次出现顺序,不能用此法
  • TreeSet 构造时传入的 Comparator 决定“重复”的含义 —— 两个元素比较结果为 0 即视为重复
  • 该方式在元素量大且已知需排序时,比先 distinct() 再 sorted() 略高效(一次遍历完成两件事)
真正容易被忽略的是:**去重逻辑必须和业务语义对齐**。比如“手机号重复算重复”和“用户名重复算重复”是两种完全不同的判定,不存在通用的“智能去重”。写代码前先明确“什么才算重复”,再选 distinct()、filter+Set 还是 toMap,比堆砌技巧重要得多。

热门AI工具

更多
小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7099

2023.08.02

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3648

2023.11.20

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2781

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

396

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

437

2026.01.06

C++ 数据结构与算法实现教程合集
C++ 数据结构与算法实现教程合集

以 C++ 为实现语言,系统讲解核心数据结构与算法,涵盖链表(单链表/双链表/环检测)、栈与队列(单调栈/优先队列)、二叉树(遍历/BST/AVL/红黑树)、哈希表(开地址法/链地址法)、图(邻接表/BFS/DFS/Dijkstra/拓扑排序)、常见排序算法(快排/归并/堆排/计数排序)的实现与复杂度分析,同时分享 LeetCode 刷题技巧、竞赛编程常用模板(二分/前缀和/滑动窗口/动态规划),帮助开发者夯实算法基础。

492

2026.05.09

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6567

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2728

2023.08.10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn