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. SDP(11):MongoDB-Engine功能实现

    根据上篇关于MongoDB-Engine的功能设计方案,我们将在这篇讨论里进行功能实现和测试.下面是具体的功能实现代码:基本上是直接调用Mongo-scala的对应函数,需要注意的是java类型和sc ...

  2. WEB前端中rem单位的应用(一)

    在最近的开发和之前的的使用中,我们一般面对需要适应多端的项目或者需要移动端多设备的适应,都可能会引入rem,em这样的单位. 如果你要着手一个以上类似的项目,我们也同样建议使用rem或者干脆引入框架, ...

  3. Navicat for MySQL下载、安装与破解

    一:下载Navicat for MySQL 进入 Navicat for MySQL下载 ,根据需要选择下载的版本,我选择的是Windows 64bit,任意选择一个镜像地址下载. 二:安装Navic ...

  4. java的枚举2

    首先先理解一下java中枚举的本质. java的世界中一切皆是类,下面通过一个例子解释一下enum的本质: package cn.xnchall.enumeration; public class G ...

  5. sql数据库中日期函数---2017-04-12

    一.SQLServer时间日期函数详解 1.  当前系统日期.时间 select getdate() 2. dateadd      在向指定日期加上一段时间的基础上,返回新的 datetime 值 ...

  6. unix及Linux发展历程

    unix及Linux发展历程 版权申明:本文资料为网上收集,由本人整理而成,转载请注明 一,unix诞生: Ken Thompson肯·汤普森 -------- unix之父 在1969年到1970间 ...

  7. 聊聊Linux用户态驱动设计

    序言 设备驱动可以运行在内核态,也可以运行在用户态,用户态驱动的利弊网上有很多的讨论,而且有些还上升到政治性上,这里不再多做讨论.不管用户态驱动还是内核态驱动,他们都有各自的缺点.内核态驱动的问题是: ...

  8. Nagios详解(基础、安装、配置文件解析及监控实例)

    一.Nagios基础 1.简介Nagios是一款开源网络监视工具.可监控网络服务(SMTP.POP3.HTTP.NNTP.ICMP.SNMP.FTP.SSH.PING---).监控主机资源.根据需求设 ...

  9. 1.Java关键字和保留字

    关键字和保留字 http://www.cnblogs.com/wwxbi/p/4292170.html 访问控制 private protected public 类,方法和变量修饰符 abstrac ...

  10. 最小化安装CentOS7的网卡设置

    实验环境:CentOS 7 Minimal Installation 64bit (1511) 最小化安装CentOS 7 后,查看网卡的信息让人很意外,因为网卡的命名规则变了,网卡的名字让人很难懂. ...