Java Set 不会重复?原来它有“记仇”的本事!

原文来自于:zha-ge.cn/java/43

Java Set 不会重复?原来它有"记仇"的本事!

前几天和同事聊天,忽然有人问: "为啥 Java 里的 Set,往里加东西,就是死活不让你重复?它心里到底咋想的?" 我一听,哈,这话题熟,讲起来比吐槽同事还顺!

Set 里的"记仇大法"

你想啊,Set,中文翻译就是"集合",但它跟"名单"可不一样。名单------随便写谁,重复也没人管。可 Java 的 Set,这可是一份"只能出现一次"的黑名单。你要是往里面塞重复的,Set 就跟个记仇精似的,死活认准你已经来过了。

为啥?其实本质上,Set 不是靠人品,靠的是底层的 hashCodeequals

  • 每次你往 Set 里丢个对象,它悄悄问自己俩问题:
    1. 这东西的 hashCode 跟别人一样吗?
    2. 如果 hashCode 一样,我还能用 equals 抖搂出真实身份吗?

只要发现"老熟人",它就直接甩锅说,喂,别进来了,等下一个吧。

代码片段来一眼

说到这儿,上点干货,给你看关键步骤:

java 复制代码
if (!set.contains(obj)) {
    set.add(obj);
}

嗯,JDK 底层其实比这个还复杂,但道理就是这么个意思。每加一个,都要"打卡登记"------否则,不让进。

踩坑瞬间

这东西好用归好用,我当年刚入职那会儿,却栽了个大跟头。

当时写了个 User 类,里面有 name 和 age,往 HashSet 里丢了一堆"看起来一模一样"的 user:

java 复制代码
User user1 = new User("小明", 11);
User user2 = new User("小明", 11);
set.add(user1);
set.add(user2);

我以为二选一,Set 肯定只留一个。结果一打印,两个都在!啊??怎么回事,这不是背叛了"不能重复"的信仰吗!

真相永远藏在 equals/hashCode

后来查了下,这才明白------ 原来自己写的 User 根本没覆写 equals 和 hashCode 啊!人家 Set 判断重复靠的就是这俩,你不写,它就只会比较引用(地址),user1 != user2,当然不当回事。

于是我灰溜溜补上:

java 复制代码
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    User user = (User) o;
    return age == user.age && Objects.equals(name, user.name);
}
// hashCode 也得覆盖!

这下,加多少"同款用户",Set 都只留一个了!

经验启示

别看 Set 冷酷,无情,其实它就是死认"你有没有本事自证身份"。用 Set 装自定义对象,千!万!记!得!

  • equals/hashCode 必须重写
  • List/数组要"包容",Set 要"守门"
  • 如果用的是 HashSet,hashCode 绝对是主要判断,TreeSet 则是 compareTo

我们程序员写类,有点像给对象办身份证。身份证号一换(equals/hashCode),Set 才认你。 要不然你每次都"离家出走换新衣服",它根本不认识你是谁!

以后见了 Set,可别只会往里塞,要让"黑名单"起作用,你得懂规则,否则老是掉进这个"重复元素不生效"的坑。

有啥用呢?去重嘛,统计嘛,社交App判好友......反正场景一大片!

行吧,今天就聊到这儿,这 Set 的"记仇大法"你可别再忘咯。哪天朋友问起,你也能一顿唠嗑吹回去嘿。

------ 代码就像生活,想不重复,可不容易 😊

相关推荐
AM越.37 分钟前
Java设计模式详解--装饰器设计模式(含uml图)
java·设计模式·uml
5980354151 小时前
【java工具类】小数、整数转中文大写
android·java·开发语言
JIngJaneIL1 小时前
基于java + vue个人博客系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
吃喝不愁霸王餐APP开发者1 小时前
Java后端服务在对接全国性霸王餐API时的多数据中心部署与就近调用策略
java·开发语言
从心归零1 小时前
springboot-jpa的批量更新方法
java·spring boot·spring
这周也會开心1 小时前
128陷阱,==与equals区别
java·开发语言
TAEHENGV2 小时前
回收站模块 Cordova 与 OpenHarmony 混合开发实战
android·java·harmonyos
a努力。3 小时前
宇树Java面试被问:方法区、元空间的区别和演进
java·后端·面试·宇树科技
2501_916766543 小时前
【面试题1】128陷阱、==和equals的区别
java·开发语言
a程序小傲3 小时前
蚂蚁Java面试被问:注解的工作原理及如何自定义注解
java·开发语言·python·面试