java编程里有关约定:如果两个对象根据equals方法比较是相等的,那么调用这两个对象的任意一个hashcode方法都必须产生相同的结果。

hashcode()和equals()都继承于object,在Object类中的定义为:

equals()方法在Object类中的定义:

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

hashCode()的定义为:

public native int hashCode();

是一个本地方法,返回的对象的地址值。

1.hashcode()和equals()是在哪里被用到的?什么用的?

HashMap是基于散列函数,以数组和链表的方式实现的。

而对于每一个对象,通过其hashCode()方法可为其生成一个整形值(散列码),该整型值被处理后,将会作为数组下标,存放该对象所对应的Entry(存放该对象及其对应值)。

equals()方法则是在HashMap中插入值或查询时会使用到。当HashMap中插入 值或查询值对应的散列码与数组中的散列码相等时,则会通过equals方法比较key值是否相等,所以想以自建对象作为HashMap的key,必须重写 该对象继承object的equals方法。

2.本来不就有hashcode()和equals()了么?干嘛要重写,直接用原来的不行么?

HashMap中,如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地 址,这样即便有相同含义的两个对象,比较也是不相等的,例如,

Student st1 = new Student("wei","man");

Student st2 = new Student("wei","man");

正常理解这两个对象再存入到hashMap中应该是相等的,但如果你不重写 hashcode()方法的话,比较是其地址,不相等!

HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等 的。若equals()不相等则认为他们不相等。如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为 同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。

如果不被重写(原生)的hashCode和equals是什么样的?
      不被重写(原生)的hashCode值是根据内存地址换算出来的一个值。
      不被重写(原生)的equals方法是严格判断一个对象是否相等的方法(object1 == object2)。
  为什么需要重写equals和hashCode方法?
      在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了
      所以这个时候我们需要重写equals方法,来满足我们的业务系统上的需求。那么为什么在重写equals方法的时候需要重写hashCode方法呢?
      我们先来看一下Object.hashCode的通用约定(摘自《Effective Java》第45页)
    在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么,对该对象调用hashCode方法多次,它必须始终如一地返回 同一个整数。在同一个应用程序的多次执行过程中,这个整数可以不同,即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。
    如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。
  如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。
     如果只重写了equals方法而没有重写hashCode方法的话,则会违反约定的第二条:相等的对象必须具有相等的散列码(hashCode)
     同时对于HashSet和HashMap这些基于散列值(hash)实现的类。HashMap的底层处理机制是以数组的方法保存放入的数据的(Node<K,V>[] table),其中的关键是数组下标的处理。数组的下标是根据传入的元素hashCode方法的返回值再和特定的值异或决定的。如果该数组位置上已经有放入的值了,且传入的键值相等则不处理,若不相等则覆盖原来的值,如果数组位置没有条目,则插入,并加入到相应的链表中。检查键是否存在也是根据hashCode值来确定的。所以如果不重写hashCode的话,可能导致HashSet、HashMap不能正常的运作、
  如果我们将某个自定义对象存到HashMap或者HashSet及其类似实现类中的时候,如果该对象的属性参与了hashCode的计算,那么就不能修改该对象参数hashCode计算的属性了。有可能会移除不了元素,导致内存泄漏。

最新文章

  1. No module named &#39;urllib2&#39;
  2. OpenSUSE 开启SSH 和网络设置
  3. Xcode7中添加3DTouch
  4. JqGrid使用经验
  5. java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
  6. Eclipse 在线安装properties编辑插件
  7. k64 datasheet学习笔记3---Chip Configuration之Times
  8. SQL Server表分区(水平分区及垂直分区)
  9. @Autowired与@Resource 详细诠释和区别(附带例子)
  10. [Robot Framework] 怎么写动态等待?
  11. 1093. Count PAT’s (25)-统计字符串中PAT出现的个数
  12. 创建Maven创建src/main/java提示反复
  13. SV中的数据类型
  14. 2018.09.14 codechef Milestone(随机化算法)
  15. 用Visual studio2012在Windows8上开发内核驱动监视进程创建
  16. jquery中动画特效方法
  17. 【转】VC++计算当前时间点间隔N天的时间(不使用CTimeSpan类)
  18. white-space——处理元素内的空白
  19. c语言编写51单片机中断程序,执行过程是怎样的?
  20. LeetCode第136题:只出现一次的数字

热门文章

  1. IISExpress.无法启动IIS Express Web 服务器.Starting IIS Express... IIS Express is running
  2. mysql查询之部门工资最高的员工
  3. OpenJudge 2755:神奇的口袋
  4. SpringBoot系列教程web篇之Thymeleaf环境搭建
  5. svn服务安装教程
  6. 【转帖】5G基站建设下的“中国速度”:北上广深领跑全国,均超1万个
  7. 使用命令进行Apache Kafka操作
  8. learning、trying、teaching
  9. Django模型层之单表操作
  10. SpringBoot与整合其他技术