当前位置:网站首页>你真的懂hashCode和equals吗???
你真的懂hashCode和equals吗???
2022-04-23 03:15:00 【小道仙97】
前言
今天还在感概说,可能三年后我的简历和刚毕业那会没啥区别,因为现在已经毕业快一年了,上次重写简历除多了两个项目经验外没啥区别,而简历上面的技术我还需要好久才能掌握。
一、关于hashCode和equals我们知道下面几点
- hashCode相同的两个对象不一定相同
- equals相同的两个对象,hashCode一定相同
- 重写equals一定要重写hashCode
其它的
- == 比较的是两个对象的内存地址值
- equals比较的是两个对象里面的值是否相同,没有重写的equals和==一样
二、hashCode的由来
我们知道hashCode是Object的方法,但是我们点进去可以看到它是一个native方法,也就是不由我们Java去实现,底层是C写的,我们理解默认的hashCode是基于内存地址生成的
public native int hashCode();
三、如何重写hashCode
重写hashCode的基本规则如下:
- 在程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值。
- 当两个对象通过equals()方法比较返回true时,则两个对象的hashCode()方法返回相等的值。
- 对象用作equals()方法比较标准的Field,都应该用来计算hashCode值。
我们根据每一个属性的hashCode,然后加上一定的规则计算出新的hashCode
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getFromUserId() == null) ? 0 : getFromUserId().hashCode());
result = prime * result + ((getFromUserName() == null) ? 0 : getFromUserName().hashCode());
result = prime * result + ((getToUserId() == null) ? 0 : getToUserId().hashCode());
result = prime * result + ((getContent() == null) ? 0 : getContent().hashCode());
result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
result = prime * result + ((getUnReadFlag() == null) ? 0 : getUnReadFlag().hashCode());
return result;
}
四、如何重写equals
- 直接判断两个对象的地址值(用 ==)
- 判断要比较的对象是否为null
- 判断两个对象是否是一个类(比较getClass)
- 调用对象的每个属性的equals进行比较,考虑到对象的属性可能为null,所以我们要先判断是否为null
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
MsgInfo other = (MsgInfo) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getFromUserId() == null ? other.getFromUserId() == null : this.getFromUserId().equals(other.getFromUserId()))
&& (this.getFromUserName() == null ? other.getFromUserName() == null : this.getFromUserName().equals(other.getFromUserName()))
&& (this.getToUserId() == null ? other.getToUserId() == null : this.getToUserId().equals(other.getToUserId()))
&& (this.getContent() == null ? other.getContent() == null : this.getContent().equals(other.getContent()))
&& (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
&& (this.getUnReadFlag() == null ? other.getUnReadFlag() == null : this.getUnReadFlag().equals(other.getUnReadFlag()));
}
注:上面的hashCode和equals都是IDEA自动生成的
五、何时需要重写equals和hashCode
我们都知道当我们在使用到HashMap这样的特殊容器的时候需要,但具体为什么需要呢?
有一个面试题是这样的:
Q: 为什么String这样的包装数据类型更适合作为hashMap的key
A:因为String这样的包装数据类型重写的hashCode和equals
事实上我们也基本上是使用String作为hashMap的key,考虑下如果我们使用自定义的类作为key会发生什么呢?
import java.util.HashMap;
import java.util.Map;
public class Test {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static Map<Test,Object> map = new HashMap<>();
static {
Test test = new Test();
test.setName("小道仙");
test.setAge(18);
map.put(test,"哇哈哈");
}
}
思考一下你有什么办法可以获取这个map里面唯一的数据呢?(除去便利,你可以使用 map.get() 方法吗?)
public static void main(String[] args) {
Test test = new Test();
test.setName("小道仙");
test.setAge(18);
System.out.println(map.get(test));
}
上面的这种方式打印出来的是null,在我们没有重写hashCode和equals之前,我们重写new的对象和之前设置进去的对象它们的hashCode和equals永不相同。
所以当我们使用自定义对象作为hashKey的时候就一定要重写hashCode和equals。
六、为什么重写了equals就一定要重写hashCode
因为的hashMap等类似的容器,每次查找都需要进行对比,如果直接使用equals当然可以,但是代价太大了,所以策略是先对比hashCode,hashCode一样再对比equals。
而不重写hashCode,默认的生成和内存地址有关,永不相同。
版权声明
本文为[小道仙97]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Tomwildboar/article/details/114295325
边栏推荐
- Aspnetcore configuration multi environment log4net configuration file
- [untitled]
- 通过 zxing 生成二维码
- If the deep replication of objects is realized through C #?
- 12.<tag-链表和常考点综合>-lt.234-回文链表
- 编码电机PID调试(速度环|位置环|跟随)
- 队列的存储和循环队列
- Web Course Design - his system
- Chapter 8 of C language programming (fifth edition of Tan Haoqiang) is good at using pointer exercises to analyze and answer
- What kind of experience is it to prepare for a month to participate in ACM?
猜你喜欢
Why is bi so important to enterprises?
“如何实现集中管理、灵活高效的CI/CD”在线研讨会精彩内容分享
2022 Shandong Province safety officer C certificate work certificate question bank and online simulation examination
Peut recevoir plusieurs paramètres de type de données - paramètres variables
Fiddler use
【VS Code】解决jupyter文件在vs code中显示异常的问题
Web Course Design - his system
类似Jira的十大项目管理软件
PID debugging of coding motor (speed loop | position loop | follow)
Maui initial experience: Cool
随机推荐
The most easy to understand service container and scope of dependency injection
《C语言程序设计》(谭浩强第五版) 第8章 善于利用指针 习题解析与答案
2022a special equipment related management (elevator) work license question bank and simulation examination
Yes Redis using distributed cache in NE6 webapi
Peut recevoir plusieurs paramètres de type de données - paramètres variables
全网最全,接口自动化测试怎么做的?精通接口自动化测试详解
《C语言程序设计》(谭浩强第五版) 第9章 用户自己建立数据类型 习题解析与答案
ThreadLocal 测试多线程变量实例
Use of ADB command [1]
[mock data] fastmock dynamically returns the mock content according to the incoming parameters
Xutils3 corrected a bug I reported. Happy
MySQL port is occupied when building xampp
2022A特种设备相关管理(电梯)上岗证题库及模拟考试
7-11 rearrange the linked list (25 points)
求二叉树的叶子结点个数
[authentication / authorization] customize an authentication handler
Knowledge of software testing~
JS recursive tree structure calculates the number of leaf nodes of each node and outputs it
Miniapi of. Net7 (special section): NET7 Preview3
The backtracking of stack is used to solve the problem of "the longest absolute path of file"