equals()与hashCode()方法总结

硅谷探秘者 3687 0 0

1.hashCode方法的作用:

        对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。

2.改写equals时总是要改写hashCode

下面这段话摘自Effective Java一书:

        1.在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一地返回同一个整数。

        2.如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。

        3.如果两个对象根据equals方法比较是不等的,则hashCode方法不一定得返回不同的整数。


        在《Java编程思想》一书中提到过这样的话:设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用 hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生 了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化 时,hashCode()方法就会生成一个不同的散列码


3.hashCode对某些集合的影响

package test;
 
import java.util.HashSet;
import java.util.Set;
 
class A{
         private String name;
         private int age;
         A(String name,int age){
                   this.name=name;
                   this.age=age;
         }
         @Override
         public boolean equals(Object obj) {
                   // TODO Auto-generated method stub
                   if(obj instanceof A){
                            A a=(A) obj;
                            if(name.equals(a.getName())&&age==a.getAge()){
                                     return true;
                            }
                   }
                   return false;
         }
         @Override
         public int hashCode() {
                   return age;
         }
         public int getAge() {
                   return age;
         }
         public void setAge(int age) {
                   this.age = age;
         }
         public String getName() {
                   return name;
         }
}
 
public class HashCodeTest {
         public static void main(String[] args) {
                   A a=new A("jiajia",1);
                   A a2=new A("wanghusai",1);
                   Set<A> set=new HashSet<A>();
                   set.add(a);
                   set.add(a2);
                   System.out.print(set.size()+"-");
                   a2.setAge(2);
                  
                   set.add(a2);
                   System.out.println(set.size());
         }
}

重写hashCode方法为:

@Override
         public int hashCode() {
                   return age;
         }
结果是:2-3


        改变a2.age后HashSet无法找到a2这个对象了,可见覆写hahcode对HashSet的存储和查询造成了影响


如果重写的Hashcode方法如下:

@Override
         public int hashCode() {
                   return name.hashCode();
         }
那么结果为:2-2

        这一点体现在:在一个应用程序运行期间,假设一个对象的equals方法做比較所用到的信息没有被改动的话。则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。


        如果只重写equals方法而不重写hashCode方法的时候:

package test;
 
import java.util.HashSet;
import java.util.Set;
 
class A{
         private String name;
         private int age;
         A(String name,int age){
                   this.name=name;
                   this.age=age;
         }
         @Override
         public boolean equals(Object obj) {
                   // TODO Auto-generated method stub
                   if(obj instanceof A){
                            A a=(A) obj;
                            if(name.equals(a.getName())&&age==a.getAge()){
                                     return true;
                            }
                   }
                   return false;
         }
         public int getAge() {
                   return age;
         }
         public void setAge(int age) {
                   this.age = age;
         }
         public String getName() {
                   return name;
         }
}
 
public class HashCodeTest {
         public static void main(String[] args) {
                   A a=new A("jiajia",1);
                   A a2=new A("jiajia",1);
                   Set<A> set=new HashSet<A>();
                   set.add(a);
                   set.add(a2);
                   System.out.print(set.size()+"-");
         }
}

        我们认为a,和a2是同一个对象,但是还是能添加进set集合,但是实际上两对象在内存中不是同一个对象,hash值是不同的。

所以:如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。


总结无论何时:

        对同一个对象调用hashcode()都应该生成同样的值。

        重写equals方法的时候应该同时重写hashCode方法。

        hashcode()尽量使用对象内有意义的识别信息。

        好的hashcode()应该产生分布均匀的散列值。



评论区
请写下您的评论...
暂无评论...
猜你喜欢
java基础 2978 java常用反射以及用packagereflect;importjava.lang.annotation.ElementType
java基础 5720 构造1.Thread(Runnabletarget)。参数为实现了Runnable接口的类。2.Thread(Stringname)。参数为线程的名字。3.Thread
框架 3521 mybatis使用接口的时候注意不能重载1.单个参数publicUsersselectUser(intid);selectid="selectUser"resultType
数据结构与算法 7893 反转链表有一个单向链表t如下:t=1-2-3-4-5-6-7-8-9写一个反转链表t如下:1-2-3-4-5-6-7-8-9=tjava代码:packagetest;/*** 节点类
java基础 2642 Java集合框架数据构是以某种形式将数据组织在一起的集合,它不仅存储数据,还支持访问和处理数据的操作。Java提供了几个能有效地组织和操作数据的数据构,这些数据构通常称为Java集合框架。在平
数据结构与算法 1406 序,若数组只有一个元素则无需操作。每次递归束时,左右两个数组都是有序的,然后对这两个中的数据进行排序,使整个数组有序。直到算束。publicclassTest8{ publicstaticint
数据结构与算法 1300 思想:把所有需要排序的数据分成两个集合,一个是待排序集合,一个是已排序的集合,算每次从未排序集合顺序或随机拿取一个数据,把它加入到已排序集合使其有序,直到未排序集合中的数据被取走完,算
数据结构与算法 1425 间隔,然后再进行分组,对每个分组进行直接插入排序。直到分组间隔小于等于1,算束。publicclassTest7{publicstaticvoidmain(Stringargs[]){inta[]=
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。