1. 把某个非零常数值,比如说17,保存在一个叫result的int类型的变量中。

2.对于对象中每一个关键域f(值equals方法中考虑的每一个域),完成以下步骤:

a.为该域计算int类型的散列吗c:

i. 如果该域是boolean类型,则计算

[java] view plain copy
f?0:1

ii. 如果该域是byte、char、short或者int类型,则计算
[java] view plain copy
(int)f

iii.如果该域是long类型,则计算
[java] view plain copy
(int)(f ^ (f >>> 32))

iv. 如果该域是double类型,则计算
[java] view plain copy
Double.doubleToLongBits(f)

得到一个long类型的值,然后按照2.a.iii,对该long型值计算散列值。

vi. 如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样对这个域递归调用hashCode,如果要求一个更为复杂的比较,则为这个域计算一个“规范表示(canonical representation)”,然后针对这个范式调用hashCode。如果这个域为null,则返回0(或者是某个常数,但习惯上使用0)。

vii. 如果该域是一个数组,则把每一个元素当做单独的域处理。也就是说,递归地应用上诉规则,对每一个重要的元素计算散列值,然后根据2.b的方法把这些散列值组合起来。

b.按照下面的公式,把步骤a得到的散列值组合到result中:

[java] view plain copy
result = 37 * result + c;

3.返回result
4.写完了hashCode后,问自己相等的实例具有相同的hashCode么?假如不是,找出原因并修正。

在散列码的计算过程中,把冗余域排除在计算之外是可以接受的。换句话说,如果一个域的值可以根据其他域值计算出来,则把这样的域排除在外是可以接受的。

举例,假如一个类PhoneNumber有三个关键域:areaCode,exchange,extension,都是short类型,则hashCode的计算过程为:

[java] view plain copy
@Override
public int hashCode(){
int result = 17;
result = result * 37 + areaCode;
result = result * 37 + exchange;
result = result * 37 + extension;
return result;
}
如果一个类是可变的,并且计算散列码的代价也比较大,那么你应该考虑把散列码缓存到对象的内部,而不是每次请求的时候都计算散列值。如果你觉得这种类型的大都数值会被用作散列键,那么你应该在实例被创建的时候计算散列值,否则,你可以选择“延迟初始化”散列码,一直到hashCode第一次调用才开始计算。
假如PhoneNumber这样处理,那么代码为:

[java] view plain copy
//延迟初始化
private volatile int hashCode = 0;

@Override
public int hashCode(){
if(hashCode == 0){
int result = 17;
result = result * 37 + areaCode;
result = result * 37 + exchange;
result = result * 37 + extension;
hashCode = result;
}
return hashCode;
}

计算hashCode的常见方法的更多相关文章

  1. 用HashSet的add方法谈hashcode和equals方法重写

    本文主要通过用HashSet的add方法讲一下hashCode和equals方法重写.错误的地方望指正. 1.了解HashSet的add方法 了解一个方法的好办法是看源码,所以先看源码 private ...

  2. java——HashCode和equal方法

    equals()反映的是对象或变量具体的值,即两个对象里面包含的值--可能是对象的引用,也可能是值类型的值. 而hashCode()是对象或变量通过哈希算法计算出的哈希值. 之所以有hashCode方 ...

  3. 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  4. 【转】 如何重写hashCode()和equals()方法

    转自:http://blog.csdn.net/neosmith/article/details/17068365 hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它 ...

  5. 关于hashMap中 计算hashCode的逻辑推理(二)

    hashMap中,为了使元素在数组中尽量均匀的分布,所以使用取模的算法来决定元素的位置.如下: //方法一: static final int hash(Object key){//jdk1.8 in ...

  6. hashcode和equals方法的区别和联系

    说到 hashcode就要和Java中的集合,HashSet,HashMap 关系最为密切. 首先附录两张Java的集合结构图: 图二:(上图的简化版) 从Set集合的特点说起 & Set是如 ...

  7. 如何重写hashCode()和equals()方法

    hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们就讨论一下如何正解理解和使用这2个方法. 如何重写equal ...

  8. 使用对象作为hashMap的键,需要覆盖hashcode和equals方法

    1:HashMap可以存放键值对,如果要以对象(自己创建的类等)作为键,实际上是以对象的散列值(以hashCode方法计算得到)作为键.hashCode计算的hash值默认是对象的地址值. 这样就会忽 ...

  9. (转)为什么要重写 hashcode 和 equals 方法?

    作者丨hsm_computer cnblogs.com/JavaArchitect/p/10474448.html 我在面试Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候 ...

随机推荐

  1. 2014-04-09 互联网Web安全职位面试题目汇总

    Domain 解释一下同源策略 同源策略,那些东西是同源可以获取到的 如果子域名和顶级域名不同源,在哪里可以设置叫他们同源 如何设置可以跨域请求数据?jsonp是做什么的? Ajax Ajax是否遵循 ...

  2. android开发之在activity中控制另一个activity的UI更新

    转自:http://blog.csdn.net/jason0539/article/details/18075293 第一种方法: 遇到一个问题,需要在一个activity中控制另一个acitivit ...

  3. 关于重定向urlrewriter.urlmapping

    大家都知道web.config 中的 urlMappings怎么用 <system.web> <urlMappings enabled="true"> &l ...

  4. 网页版电子表格控件tmlxSpreadsheet免费下载地址

    tmlxSpreadsheet 是一个由JavaScript 和 PHP 写成的电子表格控件(包含WP插件, Joomla插件等等).. 程序员可以容易的添加一个类似Excel功能的,可编辑的表格功能 ...

  5. C++ using namespace std(转载)

    转载自http://www.kuqin.com/language/20080107/3532.html 感谢这位大神的解答! 以下的内容摘抄自转载的文章里面的部分内容. 早些的实现将标准库功能定义在全 ...

  6. linux命令:find

    1.命令介绍: find用来在整个系统指定的路径下搜索文件,功能强大,但是遍历整个系统时很耗时间. 2.命令格式: find 路径 [选项] [print -exec -ok...] 3.命令参数: ...

  7. JS运动基础(四) 碰撞运动

    碰撞运动撞到目标点,速度反转无重力的漂浮Div速度反转滚动条闪烁的问题过界后直接拉回来 加入重力反转速度的同时,减小速度纵向碰撞,横向速度也减小横向速度小数问题(负数) <!DOCTYPE HT ...

  8. vim编辑下Python2.0自动补全

    Python自动补全有vim编辑下和python交互模式下,下面分别介绍如何在这2种情况下实现Tab键自动补全. 一.vim python自动补全插件:pydiction 可以实现下面python代码 ...

  9. Python 基礎 - bytes數據類型

    三元運算 什麼是三元運算?請看下圖說明 透過上圖說明後,可以得出一個三元運算公式: result = 值1 if 條件 else 值2, 如果鯈件為真: result = 值1 如果鯈件為假: res ...

  10. Map/Reduce 工作机制分析 --- 数据的流向分析

    前言 在MapReduce程序中,待处理的数据最开始是放在HDFS上的,这点无异议. 接下来,数据被会被送往一个个Map节点中去,这也无异议. 下面问题来了:数据在被Map节点处理完后,再何去何从呢? ...