0

0

如何在Java中使用HashSet_基于HashMap的无序不可重复集合实战

P粉602998670

P粉602998670

发布时间:2026-03-14 12:27:01

|

567人浏览过

|

来源于php中文网

原创

HashSet底层基于HashMap实现,元素作为key存储,value统一使用静态Object实例PRESENT;其性能、扩容、线程安全性均继承自HashMap,必须重写hashCode()和equals()以保证去重正确性。

如何在java中使用hashset_基于hashmap的无序不可重复集合实战

HashSet底层就是HashMap,但value用的是同一个Object实例

HashSet不存重复元素,靠的是内部封装的HashMap——它把元素当key存,value统一用一个叫PRESENT的静态Object占位。所以你调add()时,实际在调map.put(e, PRESENT)

这意味着:HashSet的性能、扩容逻辑、线程安全性,全都继承自HashMap。别以为“只是个集合”就和Map无关,改HashSet容量本质就是在调HashMap的initialCapacityloadFactor

  • HashSet构造时传的initialCapacity,会直接传给内部HashMap;传loadFactor也是同理
  • 如果往HashSet里放大量自定义对象,必须重写hashCode()equals()——否则HashMap找不到key,就等于“重复元素没被去重”
  • HashSet不是线程安全的,多线程写入可能破坏内部HashMap结构,抛ConcurrentModificationException或静默出错

add()返回false不一定是重复,也可能是null值被拒绝

HashSet允许存null,但只允许一个。当你连续两次add(null),第二次返回false,看起来像重复,其实是HashMapnull key的特殊处理:它把null固定放在table[0]的链表/红黑树上,且只存一次。

这个行为容易误判成“业务逻辑冲突”,尤其在集合用于状态标记(比如记录已处理ID)时,null混在里面会让排查变困难。

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

  • 如果业务中null有明确语义(如“未初始化”),建议提前过滤,别依赖HashSet来“容错”
  • 调试时看到add()返回false,先检查是不是刚加过null,而不是急着查equals()实现
  • contains(null)是合法操作,返回truefalse取决于是否真存过null,不是空指针异常

遍历顺序完全不可预测,别依赖for-each输出顺序

HashSet没有顺序保证,哪怕两次插入相同元素,for-eachiterator()返回的顺序也可能不同。这不是bug,是HashMap桶数组+哈希扰动+链表/红黑树切换共同导致的自然结果。

PatentPal专利申请写作
PatentPal专利申请写作

AI软件来为专利申请自动生成内容

下载

有人在测试环境看到“好像有序”,是因为小数据量下哈希后恰好落在连续桶里,或者JDK版本、JVM参数影响了哈希算法细节——上线后立刻打脸。

  • 需要顺序,请用LinkedHashSet(按插入顺序)或TreeSet(按自然序/比较器)
  • 单元测试里断言集合内容时,别用assertEquals(list, new ArrayList(set)),而要用assertTrue(set.containsAll(expected) && expected.containsAll(set))
  • 日志打印HashSet内容时,如果为可读性临时转ArrayListsort(),记得注明这只是为了展示,不影响业务逻辑

内存占用比ArrayList高不少,小集合别硬套

一个空HashSet默认初始化16个桶,每个桶是个Node数组引用,加上HashMap自身字段(sizemodCount等),基础开销约80字节;而ArrayList空实例才12字节左右。存10个Integer,HashSet可能占300+字节,ArrayList不到200字节。

这不是理论数字——在高频创建短生命周期集合的场景(比如方法内临时去重),差异会放大成GC压力。

  • 元素少于5个、且不频繁增删时,用Arrays.asList() + 手动contains()查重,往往比新建HashSet更轻量
  • 如果确定元素范围小且固定(比如状态码0-9),用boolean[]BitSet替代,内存和速度都碾压
  • HashSetremove()平均O(1),但最坏O(n)(哈希全碰撞),而ArrayList.remove(Object)稳定O(n);别只看大O,要看你的数据分布

真正麻烦的从来不是“怎么用HashSet”,而是没想清楚“为什么非得用HashSet”。哈希计算、桶扩容、对象包装——每一步都在悄悄吃资源。用之前,先问自己:这个去重,真的值得扛这一套机制?

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

367

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

42

2025.11.30

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

409

2023.09.04

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

766

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

377

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

33

2026.01.21

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 82.1万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号