Object类的hashCode方法:

public native int hashCode();   是一个本地方法。

其中这个方法的主要注释如下:

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method
must consistently return the same integer, provided no information used in equals comparisons on the object is modified.

在一次应用程序执行期间,只要对象的equals方法没有改变,那么对于同一个对象无论调用多少次hashCode方法,都应该返回同一个整数。
This integer need not remain consistent from one execution of an application to another execution of the same application.

在应用程序的多次执行时,调用hashCode方法,每次执行的返回整数可以不一样 。

If two objects are equal according to the equals(Object)  method, then calling the hashCode method on each of  the two objects must produce the same integer result.

如果两个对象根据equals方法返回的结果是true,即这两个对象是逻辑相等的,那么这两个对象的hashCode方法应该返回同一个整数。

It is not required that if two objects are unequal  according to the {@link java.lang.Object#equals(java.lang.Object)}  method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

如果两个对象根据equals方法返回的结果是false,即这两个对象不是逻辑相等的,那么这两个对象的hashCode方法可以返回同一个整数,也可以返回不同的整数,

但是,程序员应该认识到对于逻辑不相等的两个对象,它们的hashCode方法返回不同的整数,有可能提高散列表的性能。

在每个覆盖了equals方法的类中,必须覆盖hashCode方法,那么就会违反上面的hashCode的通用约定,这样导致该类无法结合所有基于散列的集合一起正常工作,

这样的集合包括HashMap,HashSet,Hashtable。

Object类的hashCode方法 ,为每个不同的实例对象返回不同的整数,如果我们覆盖了equals方法,而继承了hashCode方法,那么就算是两个逻辑相等的对象,对于hashCode方法来说,也是两个不同的实例对象,也返回的是不同的整数。

如何写一个好的hashCode方法:

自定义散列函数 ,产生的散列值,使得逻辑相同的对象有相同的散列值(放入同一个桶中),逻辑不同的对象有不同的散列值(放入不同的桶中)。

结合equals方法的关键域,有如下步骤:

1.把一个非零的常数值,如17,保存在一个名叫result的int变量中;

2.对于equals方法中的关键域产生int类型散列值:

boolean类型的域(如名叫f)      计算(f?1:0)

byte,char,short,int类型的域      计算 (int)f

long类型的域                          计算 (int)(f^(f>>>32))

float类型的域                          计算 Float.floatToIntBits(f)

double类型的域                       计算  Double.doubleToLongBits(f)

引用类型的域                           使用 引用类型的hashCode方法得到的散列值

数组类型的域                           把数组中的每个元素当成一个关键域,计算出散列值。

3.对于每一个关键域计算出来的散列值 (如名叫c)

result = result * 31 + c;

最后放回这个result整数   就是计算出来的当前调用hashCode方法得到的散列值。

注意不要试图从散列值的计算过程中排除一个关键域来提高散列值计算的性能。

关于散列表:

相同散列值的对象被放入同一个桶中,这样寻找一个对象时,先算出这个对象的散列值,就知道到哪个桶中去找这个对象了 ,提高了查找性能。

第九条:覆盖equals方法时总要覆盖hashCode方法的更多相关文章

  1. 【Java实战】源码解析为什么覆盖equals方法时总要覆盖hashCode方法

    1.背景知识 本文代码基于jdk1.8分析,<Java编程思想>中有如下描述: 另外再看下Object.java对hashCode()方法的说明: /** * Returns a hash ...

  2. 覆盖equals的时候总要覆盖hashCode

    import java.util.HashMap; public class Student { private String name ; private String id; public Stu ...

  3. 半夜思考, 为什么建议重写 equals() 方法时, 也要重写 hashCode() 方法

    我说的半夜, 并不是真正的半夜, 指的是在我一个人的时候, 我会去思考一些奇怪的问题. 要理解 hashCode() 需要理解下面三个点: hash契约 哈希冲突 哈希可变 第一点: hash 契约指 ...

  4. 覆盖equals时总要覆盖hashCode

    本文涉及到的概念 1.为什么重载equals方法时,要重载hashCode函数;没有重载hashCode带来的问题 2.一个对象hashCode的生成规则       1.为什么重载equals方法时 ...

  5. JAVA中重写equals()方法的同时要重写hashcode()方法

    object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...

  6. Item 9 覆盖equals时总要覆盖hashCode

    为什么覆盖equals时,总要覆盖hashCode?   原因是,根据Object规范: 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCod ...

  7. 第9条:覆盖equals时总要覆盖hashCode

    在每个覆盖equals方法的类中,也必须覆盖hashCode方法.否则,会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,包括HashMap,Hash ...

  8. Effective Java —— 覆盖equals时总要覆盖hashCode

    本文参考 本篇文章参考自<Effective Java>第三版第十一条"Always override hashCode when you override equals&quo ...

  9. why在重写equals时还必须重写hashcode方法

    首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...

随机推荐

  1. mybatis快速入门(二)

    这次接着上次写增删改查吧. 现将上节的方法改造一下,改造测试类. package cn.my.test; import java.io.IOException; import java.io.Inpu ...

  2. NOIP2017+停课总结

    注意 此文章禁止一切含虚伪内容的评论,违者删除评论 其删除解释权归博主所有 Part1 论yyb NOIP 如何炸裂 前言 离NOIP已有三个星期,忘却的救主快要降临了吧,我正有写一篇总结的必要了.. ...

  3. 【USACO09OCT】热浪Heat Wave

    题目描述 The good folks in Texas are having a heatwave this summer. Their Texas Longhorn cows make for g ...

  4. AWS 认证攻略(SA)

    很高兴经过一个多月的努力顺利pass了自己的SA认证,同事说证都是虚的,不过考个证也算是对自己实力的认可吧,博主第一次写博文,先简单的写一些认证的攻略吧 1.博主11月正式入职云服务提供商,领导要求每 ...

  5. 【Spring源码分析】原型Bean实例化过程、byName与byType及FactoryBean获取Bean源码实现

    原型Bean加载过程 之前的文章,分析了非懒加载的单例Bean整个加载过程,除了非懒加载的单例Bean之外,Spring中还有一种Bean就是原型(Prototype)的Bean,看一下定义方式: & ...

  6. python之hasattr()、 getattr() 、setattr() 函数

    这三个方法可以实现反射和内省机制,在实际项目中很常用,功能也很强大. [转]http://www.cnblogs.com/cenyu/p/5713686.html hasattr(object, na ...

  7. Python3基础教程1——Python的环境搭建

    2018年3月8日 当然推荐一个比较系统的教程 http://www.runoob.com/python3/python3-tutorial.html 人家也写的也比我好啦 本教程为新手向的,请大佬跳 ...

  8. 【前端单元测试入门04】Karma

    Karma 官方介绍 A simple tool that allows you to execute JavaScript code in multiple real browsers. 即一个允许 ...

  9. 如何实现vue前端跨域,proxyTable解决开发环境前端跨域问题

    在开发环境与后端调试的时候难免会遇到跨域问题,很多人说跨域交给后端解决就好了. 其实不然,前端也有很多方法可以解决跨域,方便也快捷. 常见的有nginx转发.node代理. 在vue项目中常用的是pr ...

  10. 【node】安装和配置node项目文件

    需要把 views文件中的子文件全部改为以 .ejs的后缀 1·npm install express -g (全局安装) 2·npm install -g express-generator (安装 ...