覆盖equals时总要覆盖hashCode
- 在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。
- 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。
- 如果两个对象根据equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生不同的整数结果。给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。
import java.util.*;
public final class PhoneNumber {
private final short areaCode;
private final short prefix;
private final short lineNumber;
public PhoneNumber(int areaCode, int prefix, int lineNumber) {
rangeCheck(areaCode, 999, "area code");
rangeCheck(prefix, 999, "prefix");
rangeCheck(lineNumber, 9999, "line number");
this.areaCode = (short) areaCode;
this.prefix = (short) prefix;
this.lineNumber = (short) lineNumber;
}
private static void rangeCheck(int arg, int max, String name) {
if (arg < 0 || arg > max)
throw new IllegalArgumentException(name + ": " + arg);
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber) o;
return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode;
}
// Broken - no hashCode method!
// A decent hashCode method - Page 48
// @Override public int hashCode() {
// int result = 17;
// result = 31 * result + areaCode;
// result = 31 * result + prefix;
// result = 31 * result + lineNumber;
// return result;
// }
// Lazily initialized, cached hashCode - Page 49
// private volatile int hashCode; // (See Item 71)
//
// @Override public int hashCode() {
// int result = hashCode;
// if (result == 0) {
// result = 17;
// result = 31 * result + areaCode;
// result = 31 * result + prefix;
// result = 31 * result + lineNumber;
// hashCode = result;
// }
// return result;
// }
public static void main(String[] args) {
Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
m.put(new PhoneNumber(707, 867, 5309), "Jenny");
System.out.println(m.get(new PhoneNumber(707, 867, 5309)));
}
}
- 把某个非0的常数值,比如17,保存在一个名为result的int类型的变量中。
- 对于对象中的每个关键域f,做如下操作:
- 为该域计算int类型的哈希值c:
- 如果该域是boolean类型,则计算(f?1:0)
- 如果该域是byte、char、short或者int类型,则计算(int)f
- 如果该域是long类型,则计算(int)(f^(f>>>32))
- 如果该域是float类型,则计算Float.floatToIntBits(f)
- 如果该域是double类型,则计算Double.doubleToLongBits(f),然后重复第三个步骤。
- 如果该域是一个对象引用,并且该类的equals方法通过递归调用equals方法来比较这个域,同样为这个域递归的调用hashCode,如果这个域为null,则返回0。
- 如果该域是数组,则要把每一个元素当作单独的域来处理,递归的运用上述规则,如果数组域中的每个元素都很重要,那么可以使用Arrays.hashCode方法。每个元素计算出来的hashCode,使用2.2中的公式,将hashCode组合起来。
- 为该域计算int类型的哈希值c:
private final short areaCode;
private final short prefix;
private final short lineNumber; @Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber) o;
return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode;
} // A decent hashCode method - Page 48
@Override public int hashCode() {
int result = 17;
result = 31 * result + (int)areaCode;
result = 31 * result + (int)prefix;
result = 31 * result + (int)lineNumber;
return result;
}
覆盖equals时总要覆盖hashCode的更多相关文章
- Item 9 覆盖equals时总要覆盖hashCode
为什么覆盖equals时,总要覆盖hashCode? 原因是,根据Object规范: 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCod ...
- 第9条:覆盖equals时总要覆盖hashCode
在每个覆盖equals方法的类中,也必须覆盖hashCode方法.否则,会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,包括HashMap,Hash ...
- Effective Java —— 覆盖equals时总要覆盖hashCode
本文参考 本篇文章参考自<Effective Java>第三版第十一条"Always override hashCode when you override equals&quo ...
- 覆盖equals 时总要覆盖hashCode(9)
2019独角兽企业重金招聘Python工程师标准>>> 1.在每个覆盖了equals 方法的类中,也必须覆盖hashCode 这是关于hashCode 的通用约定 这样可以与 基于散 ...
- 覆盖equals()时总要覆盖hashCode()
覆写如下: public class User{ private Integer id; private String userName; private String passWord; publi ...
- 【Effective Java】5、覆盖equals时总要覆盖hashcode
package cn.xf.cp.ch02.item9; import java.util.HashMap; import java.util.Map; public class PhoneNumbe ...
- EffectiveJava(9)覆盖equals是总要覆盖hashCode
覆盖equals是总要覆盖hashCode 通过散列函数将集合中不相等的实例均匀的分布在所有可能的散列值上 1.把某个非零的常数值保存在一个名为result的int类型变量中 2.对于对象中每个关键域 ...
- 第8条:覆盖equals时遵守通用约定
如果不需要覆盖equals方法,那么就无需担心覆盖equals方法导致的错误. 什么时候不需要覆盖equals方法? 1.类的每个实例本质上是唯一的. 例如对于Thread,Object提供的equa ...
- Item 8 覆盖equals时请遵守通用约定
在覆盖equals方法的时候,你必须要遵守它的通用约定,不遵守,写出来的方法,会出现逻辑错误.下面是约定的内容: equals方法实现了等价关系: 自反性.对于任何非null的引用值,x.eq ...
随机推荐
- lintcode-425-电话号码的字母组合
425-电话号码的字母组合 Given a digit string excluded 01, return all possible letter combinations that the num ...
- 第15章 磁盘配额(Quota)与高级文件系统管理
磁盘配额(quota)的应用与实践 什么是quota 举例来说,用户的默认主文件夹是在/home下面,如果/home是个独立的分区,假设是10G,/home下有30个账号,这样30个用户共享这10G的 ...
- mac python install zlib not available
用brew install 3.4.4(python)时报 zipimport.ZipImportError: can't decompress data; zlib not available 的错 ...
- 软件工程个人作业3——集大通APP案例分析
第一部分:调研, 评测 1.第一次上手体验 主要界面截图: 感受: 1.界面不美观: 2.特色功能展现模块不突出,以上截图为打开APP所看到的界面展示,但是这些功能都不是该APP的特色功能,显得有些累 ...
- 关于“问吧APP”问卷调查报告分析与体会
上周根据我们走廊奔跑队的“问吧APP”项目对本校范围内的学生发放了上百份调查问卷,并对此作出了统计和整理.针对我们项目所提出的问题涉及到的用户信息有性别.年龄.学历.职业.平时上网途径以及对 ...
- 个人项目----词频统计WEB(部分功能)
需求分析 1.使用web上传txt文件,对上传的txt进行词频统计. 2.将统计后的结果输出到web页面,力求界面优美. 3.在界面上展示所给url的文章词频统计,力求界面优美. 3.将每个单词同四. ...
- HDU 2132 An easy problem
http://acm.hdu.edu.cn/showproblem.php?pid=2132 Problem Description We once did a lot of recursional ...
- google auth
思路: secret 系统生成的密钥 把密钥分配给某个用户,用户可以把这个密钥加入到app中,app会1min生成一个code: 验证时,根据用户的 secret ,系统生成一个code,再比较用户输 ...
- WordPress使用淘宝IP地址库的API显示评论者的位置信息(二)
1 淘宝IP地址库的接口说明 在上一篇文章<WordPress使用淘宝IP地址库的API显示评论者的位置信息(一)>中,vfhky使用了新浪工具提供的这个IP接口显示博客评论者的位置信息. ...
- Hibernate 中 load() 和 get() 的区别
get 和 load 方式都是是根据 id 取得一个记录.下边详细说一下 get 和 load 的不同,因为有些时候为了对比也会把 find 加进来. 1.从返回结果上对比: load 方式检索不到的 ...