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

推荐订阅源

H
Help Net Security
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cisco Talos Blog
Cisco Talos Blog
P
Privacy & Cybersecurity Law Blog
I
Intezer
Y
Y Combinator Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
N
Netflix TechBlog - Medium
The Hacker News
The Hacker News
AWS News Blog
AWS News Blog
aimingoo的专栏
aimingoo的专栏
A
About on SuperTechFans
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Stack Overflow Blog
Stack Overflow Blog
Hacker News: Ask HN
Hacker News: Ask HN
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
B
Blog
T
Tor Project blog
C
Cybersecurity and Infrastructure Security Agency CISA
云风的 BLOG
云风的 BLOG
博客园_首页
V2EX - 技术
V2EX - 技术
T
Threat Research - Cisco Blogs
腾讯CDC
宝玉的分享
宝玉的分享
博客园 - 叶小钗
罗磊的独立博客
S
Securelist
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
Scott Helme
Scott Helme
博客园 - 司徒正美
W
WeLiveSecurity
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Secure Thoughts
NISL@THU
NISL@THU
N
News and Events Feed by Topic
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
K
Kaspersky official blog
IT之家
IT之家

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()方法,其他程序员或者其他工具类按照标准去使用你的定制类就会出现错误。