惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
N
News and Events Feed by Topic
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
The Cloudflare Blog
H
Heimdal Security Blog
Schneier on Security
Schneier on Security
Engineering at Meta
Engineering at Meta
Google Online Security Blog
Google Online Security Blog
宝玉的分享
宝玉的分享
AI
AI
The GitHub Blog
The GitHub Blog
MongoDB | Blog
MongoDB | Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
The Last Watchdog
The Last Watchdog
T
Troy Hunt's Blog
S
Security @ Cisco Blogs
H
Hacker News: Front Page
F
Fortinet All Blogs
博客园_首页
S
Secure Thoughts
N
News and Events Feed by Topic
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
Spread Privacy
Spread Privacy
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Hugging Face - Blog
Hugging Face - Blog
Hacker News: Ask HN
Hacker News: Ask HN
C
CXSECURITY Database RSS Feed - CXSecurity.com
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
L
LINUX DO - 最新话题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
Know Your Adversary
Know Your Adversary
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Scott Helme
Scott Helme
P
Privacy & Cybersecurity Law Blog
S
Securelist
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
O
OpenAI News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
PCI Perspectives
PCI Perspectives
L
LangChain Blog
雷峰网
雷峰网
Security Archives - TechRepublic
Security Archives - TechRepublic
V2EX - 技术
V2EX - 技术

Xudong's Blog

AI杀死了个人博客 让MDC在各种线程间穿梭自如 新手选购微单的策略 一些让Python代码更快的技巧 HTTP报文结构 Python日志库logging总结 写定向爬虫时遇到的问题 Java中的协变与逆变 给Hexo主题添加LaTeX公式支持 Python3中的Iterator与Iterable Rss订阅源分享 Git Tips Redis的数据库与持久化 Redis中的数据结构 控制反转与依赖注入 Vim命令笔记 Java中对象域的初始化 Java中的基本类型和自动装拆箱 Hello, world. 使用Hexo搭建静态博客
Java中的equals和hashCode方法
Xudong Sun · 2018-10-04 · via Xudong's Blog

equals()

java中处处是对象。所有类都继承自Object基类,Object基类拥有一个equals()方法。所以无论是继承自Object,还是override了基类的,所有类都拥有equals()方法。

1
2
3
public boolean equals(Object obj) {
return (this == obj);
}

上面是Object类的equals()方法,很简单,使用了 == 比较了两个对象。
而 == 是java中的运算符,用在两个对象的引用之间时,作用是比较两个对象的地址。
所以那个类如果没有override这个方法,在其对象上使用equals()和==是等效的。

1
2
3
4
5
6
7
8
9
10
11
public void compareObject() {
StringBuffer strOne = new StringBuffer("String");
StringBuffer strTwo = new StringBuffer("String");
System.out.println(strOne==strTwo);
System.out.println(strOne.equals(strTwo));

Integer intOne = new Integer(999);
Integer intTwo = new Integer(999);
System.out.println(intOne==intTwo);
System.out.println(intOne.equals(intTwo));
}
1
2
3
4
false
false
false
true

StringBuffer也是一种字符串类,需要注意的是它没有override基类的equals方法。所以即使对象中的内容一样,equals()返回的也是false。
而Integer类实现了它自己的equals()方法,内容同样是999的两个对象被equals()正确判断为true。

下面是Integer类实现的equals()

1
2
3
4
5
6
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

如果我们自己写的类也需要进行比较,那么我们实现的equals()需要比较我们类对象中的内容,这样才符合java规范。

hashCode()

接下来说一下这两个方法的关系。

如果一个类需要重写equals()方法,那么同时也应该重写hashCode()方法。因为java文档规定了,如果A.equals(B)返回为true,那么A.hashCode()应当等于B.hashCode()。

Effective Java 3rd edition
Item 11 : Always override hashCode when you override equals

为什么要这样呢?首先从HashMap的源码我们知道,当从map中找一个指定的key时,我们首先是根据这个key的hashCode()的返回值经过处理后生成的hash值找到对应的桶,再遍历这个桶找到相等的key。

从以上过程可以提炼出非常重要的一点,相等的对象hashCode()返回值一定要相等,因为如果hashCode()返回值不相等的话,计算出来的hash值很可能是不相等的,这会直接导致相同的key可能放入不同的桶中,这是不被允许的。所以如果我们要用自定义类对象做散列表的key时,在重写了equals()后,还要重写hashCode()来保证equals()返回为true的情况下两个对象hashCode()的返回值也相等。

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Test {
public static void main(String[] args) {
HashMap<People, Integer> map = new HashMap<>();

People p1 = new People(11, "Jack");
People p2 = new People(11, "Jack");

map.put(p1, 1);


System.out.println(map.get(p2));
}
}

class People {
int age;
String name;

public People(int age, String name) {
this.age = age;
this.name = name;
}


@Override
public boolean equals(Object obj) {
return ((People) obj).age == age && ((People) obj).name.equals(name);
}


@Override
public int hashCode() {
return age * name.hashCode();
}
}

总结

为了避免在使用散列容器出现错误,当我们重写自定义类的equals()方法时,还要重写hashCode()方法,以保证相等的对象hashCode()返回值必定相等。

如果忽略了equals()以及hashCode()方法,其他程序员或者其他工具类按照标准去使用你的定制类就会出现错误。