关于hashCode和equals重写
规则
只要重写equals,就必须重写hashCode。
用Set存储对象或者用对象作为Map的键时,必须重写hashCode。也就是说,当需要用对象的哈希值来判断对象是否相等时必须重写hashCode。
说明:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。
介绍
- Equals的作用是用来判断两个对象是否相等。
- hashCode 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数,这个哈希码的作用是确定该对象在哈希表中的索引关系。
关系(我们以“类的用途”来将“hashCode()和equals()的关系”分两种情况来说明)
不会创建“类对应的散列表”
不会创建类对应的散列表是说:我们不会在HashSet, Hashtable, HashMap等等这些本质是散列表的数据结构中,用到该类。例如,不会创建该类的HashSet集合,不会以该类作为Map的键。在这种情况下,hashCode和 equals是没有关系的。而hashCode() 则根本没有任何作用。
equals() 用来比较该类的两个对象是否相等,必要时还是需要重写。以下这种情况按照正常业务应该返回true,但是实际结果却是false。
public static void main(String[] args) {
Student student1 = new Student();
student1.setName("张三");
student1.setAge(1); Student student2 = new Student();
student.setName("张三");
student.setAge(1); System.out.println(student1.equals(student2));
}
重写equals我们就可以根据我们实际的情况来判断是否相等。
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
这种情况下,hashCode没有实际意义
会创建类对应的散列表
创建类对应的散列表是说:我们会在HashSet,Hashtable,HashMap等等这些本质是散列表的数据结构中,用到该类。在这种情况下,该类的“hashCode()和equals()”是有关系的:
- 如果两个对象相等,那么hashCode返回的值一定相等,通过equals比较两个对象也相等。
- 如果两个对象hashCode()相等,它们并不一定相等。因为在散列表中,hashCode相等,即两个键值对的哈希值相等。然而哈希值相等,不一定能得出键值对相等。补充说一句:“两个不同的键值对,哈希值相等”,这就是哈希冲突。
总结
以程序角度看图1中student1和student2必然是两个不同的对象,new对象的时候JVM分配的不通的内存。但是以业务和面向对象来看,student1和student2的所有属性都相同,我们必须把他们当成同一个对象来处理。需要比较的时候我们则需要重写equals来具体比较对象的属性值,用Set去重时我们也得重写hashCode来给这种相对的对象返回相等的哈希值。如果没有以上需求则不用重写hashCode和equals,这两者也没有关系。这是自己对重hashCode和equals的理解,因为自己技术菜理解比较片面。专业解释还请看 说说hashCode() 和 equals() 之间的关系。
类对应的散列表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
关于hashCode和equals重写的更多相关文章
- java equals重写
@Override public boolean equals(Object obj) { if(this == obj) { return true; ...
- hashCode 和 equals 的区别
今天记录一下hashCode的知识,以前都没有怎么接触过的,感觉还是很陌生,专门去学习了一下 首先我最大的问题就是hashCode究竟是干什么 的,现在也一知半解了吧, 哈希值是一个对象的地址值,是一 ...
- 用HashSet的add方法谈hashcode和equals方法重写
本文主要通过用HashSet的add方法讲一下hashCode和equals方法重写.错误的地方望指正. 1.了解HashSet的add方法 了解一个方法的好办法是看源码,所以先看源码 private ...
- java集合框架(hashSet自定义元素是否相同,重写hashCode和equals方法)
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不一致,元素不可以重复 * (通过哈希值来判断是否是同一个对象) * ----HashSet:底层数据结构是哈希表, * 保证 ...
- 为什么要重写 hashcode 和 equals 方法?
引言 以前面试的时候被面试官问到过这样一个问题: 你有没有重写过 hashCode 方法? 心里想着我没事重写哪玩意干啥,能不写就不写.嘴上当然没敢这么说,只能略表遗憾的说抱歉,我没写过. 撇了面试官 ...
- 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。
我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...
- 【转】 如何重写hashCode()和equals()方法
转自:http://blog.csdn.net/neosmith/article/details/17068365 hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它 ...
- java为什么要重写hashCode和equals方法?
如果不被重写(原生)的hashCode和equals是什么样的? 不被重写(原生)的hashCode值是根据内存地址换算出来的一个值. 不被重写(原生)的equals方法是严格判断一个对象是否相等的方 ...
- 正确重写hashcode hashcode与equals方法 集合元素如何判断是否相等 集合如何查看是否包含某个元素
首先记住两句话 相等的两个对象,即equals(Object)方法判断两个对象相等,那么他们必须要有相同的hashcode hashcode相同的两个对象,他们可能相同,也可能不相同 简单地说可以这么 ...
- 关于HashMap自定义key重写hashCode和equals的问题
使用HashMap,如果key是自定义的类,就必须重写hashcode()和equals() hashcode()和equals()都继承于object,在Object类中的定义为: equals( ...
随机推荐
- 驱动开发:通过SystemBuf与内核层通信
内核层与应用层之间的数据交互是必不可少的部分,只有内核中的参数可以传递给用户数据才有意义,一般驱动多数情况下会使用SystemBuf缓冲区进行通信,也可以直接使用网络套接字实现通信,如下将简单介绍通过 ...
- 【译】命名变得简单:AI 支持的重命名建议
您是否曾经为命名一个变量.方法或类而挣扎过?找到表达性和简洁性之间的完美平衡了吗?您并不孤单.我们通过 GitHub Copilot Chat 扩展(需要订阅)在最新的 Visual Studio 预 ...
- Leetcode刷题第五天-二分法-回溯
215:第k个最大元素 链接:215. 数组中的第K个最大元素 - 力扣(LeetCode) em~~怎么说呢,快速选择,随机定一个目标值,开始找,左边比目标小,右边比目标大,左右同时不满足时,交换左 ...
- java代码实现自动生成数据库表er图
最近有同事看到字节跳动产品设计文档里有数据库表er图.就想问问又没有现成的工具也给直接生成一个er图,经查找验证发现并没有.因为现在表关系都是用的逻辑外键而非物理外键约束的,所以像navicat等工具 ...
- [Java]HashMap与ConcurrentHashMap的一些总结
HashMap与ConcurrentHashMap的一些总结 HashMap底层数据结构 JDK7:数组+链表 JDK8:数组+链表+红黑树 JDK8中的HashMap什么时候将链表转为红黑树? 当发 ...
- Spring Boot + MyBatis-Plus 实现 MySQL 主从复制动态数据源切换
MySQL 主从复制是一种常见的数据库架构,它可以提高数据库的性能和可用性.动态数据源切换则可以根据业务需求,在不同场景下使用不同的数据源,比如在读多写少的场景下,可以通过切换到从库来分担主库的压力. ...
- 从零开始的react入门教程(六),一篇文章理解react组件生命周期
壹 ❀ 引 学习任何一门框架,无论是vue.react亦或是angular,我们除了需要熟练掌握框架语法外,了解框架自身的生命周期也是至关重要的.一方面生命周期在面试中多多少少总是会提及,其次了解框架 ...
- Python递归遍历目录并删除文件中的前N行
1 import os 2 3 # 遍历目录下的所有文件 4 def check_file(file_path): 5 os.chdir(file_path) 6 print(os.path.absp ...
- SpringBoot相关注解使用
@MapperScan注解和@Mapper @Mapper常用在相应的 *Mapper类上,但是每个类都使用相对麻烦,所以后来用@MapperScan替代 ,@MapperScan注解使用在启动类上. ...
- Vim常用快捷键汇总
跳到指定行 在命令行模式下输入: :n(n为指定行号)