【JAVA】hashcode() & equals()
平时使用map时都是用JAVA原生的类型,所以很少关注到hashcode()和equals()的方法的内部实现。近期实现一个小工具,涉及到自己写的类的查找比对,又再次重温了相关的知识。
上简单示例代码,比对自己覆写和不覆写的差异
不覆写hashcode()和equals():
import java.util.HashMap;
import java.util.Map; public class HashCode_Equals { public int a;
public int b; public static void main(String[] args) { Map<HashCode_Equals, String> map = new HashMap<HashCode_Equals, String>(); HashCode_Equals obj1 = new HashCode_Equals();
obj1.a = 1;
obj1.b = 1;
map.put(obj1, "test"); HashCode_Equals obj2 = new HashCode_Equals();
obj2.a = 1;
obj2.b = 1; System.out.println("obj1.equals(obj2)=" + obj1.equals(obj2));
System.out.println("map.get(obj2)=" + map.get(obj2));
}
}
执行结果:
obj1.equals(obj2)=false
map.get(obj2)=null
仅覆写equals()方法
import java.util.HashMap;
import java.util.Map; public class HashCode_Equals { public int a;
public int b; @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
HashCode_Equals other = (HashCode_Equals) obj;
if (a != other.a)
return false;
if (b != other.b)
return false;
return true;
} public static void main(String[] args) { Map<HashCode_Equals, String> map = new HashMap<HashCode_Equals, String>(); HashCode_Equals obj1 = new HashCode_Equals();
obj1.a = 1;
obj1.b = 1;
map.put(obj1, "test"); HashCode_Equals obj2 = new HashCode_Equals();
obj2.a = 1;
obj2.b = 1; System.out.println("obj1.equals(obj2)=" + obj1.equals(obj2));
System.out.println("map.get(obj2)=" + map.get(obj2));
} }
执行结果:
obj1.equals(obj2)=true
map.get(obj2)=null
同时覆写hashcode()和equals()(借用eclipse集成的功能自动生成)
import java.util.HashMap;
import java.util.Map; public class HashCode_Equals { public int a;
public int b; @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + a;
result = prime * result + b;
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
HashCode_Equals other = (HashCode_Equals) obj;
if (a != other.a)
return false;
if (b != other.b)
return false;
return true;
} public static void main(String[] args) { Map<HashCode_Equals, String> map = new HashMap<HashCode_Equals, String>(); HashCode_Equals obj1 = new HashCode_Equals();
obj1.a = 1;
obj1.b = 1;
map.put(obj1, "test"); HashCode_Equals obj2 = new HashCode_Equals();
obj2.a = 1;
obj2.b = 1; System.out.println("obj1.equals(obj2)=" + obj1.equals(obj2));
System.out.println("map.get(obj2)=" + map.get(obj2));
} }
执行结果:
obj1.equals(obj2)=true
map.get(obj2)=test
关于equals()方法不再多余介绍,重点篇幅是关于hashcode()的如何更好实现
《effective java》第9条:覆盖equals时总要覆盖hashcode

规范要求:相等的对象必须有相同的散列码。否则从map中当作key值得到的散列码是不同的,从而取到的value结果是不同的,上述的例子就是一个很好的证明
在不覆写的情况下,hashcode方法是JAVA默认生成的。从代码执行结果看obj1.equals(obj2)为true时,仍然hashcode不同,也就说JAVA默认的是不符合要求的,要求我们必须覆写。
关于hashcode,如果方法写的简单会造成hashcode的不断冲突,这样每个对象被映射到同一个散列桶中,使得散列表退化为链表。使得本应线性时间运行的程序变成了平方级在运行。
所以effecive java同时给了实现的参考

【JAVA】hashcode() & equals()的更多相关文章
- 【Java】hashcode()和equals()
大家知道,在集合中判断集合中的两个元素是否相同,依赖的是hashcode()和equals()两个方法. > 一个简单的实验 public class Teacher { private Int ...
- 【Java】 hashcode()和System.identityHashCode()
hashcode()和System.identityHashCode() openjdk8: http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/5b86f ...
- 【Java】-NO.16.EBook.4.Java.1.008-【疯狂Java讲义第3版 李刚】- 集合/容器
1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.008-[疯狂Java讲义第3版 李刚]- 集合 Style:EBook Series:Java Si ...
- 【Java】-NO.12.Java.2.OCJP.1.001-【Java OCJP】-
1.0.0 Summary Tittle:[Java]-NO.12.Java.2.OCJP.1.001-[Java OCJP]- Style:Java Series:OCJP Since:2017-0 ...
- 【Java】代处理?代理模式 - 静态代理,动态代理
>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...
- 【Java】-NO.16.EBook.4.Java.1.007-【疯狂Java讲义第3版 李刚】- Java基础类
1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.007-[疯狂Java讲义第3版 李刚]- Java基础类 Style:EBook Series:J ...
- 【Java】-NO.16.EBook.4.Java.1.002-【疯狂Java讲义第3版 李刚】- 数据类型
1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.002-[疯狂Java讲义第3版 李刚]- 数据类型 Style:EBook Series:Java ...
- 【Java】 子字符串的比较(substring的==与equal()使用)
public class Test { public static void main(String[] args) { String str1="good"; System.ou ...
- 【Java】代理模式,静态代理和动态代理(基于JDK或CGLib)
当我们需要在一个方法之前或之后添加一段逻辑时,自然会想到使用代理类.代理类帮我们代理了实际类的调用,然后可以在实际调用之前和之后添加一些逻辑,从而不浸入实际类. 拓展:由于代理类能在实际类调用之前和之 ...
随机推荐
- IDA分析脱壳后丢失导入表的PE
1. 问题 一些程序经过脱壳后(如用OD的dump插件),一些导入表信息丢失了,导致拖入IDA后看不到API的信息(如右图所示,第一个红圈处实际是GetCurrentProcessId),给分析造成极 ...
- Linux第四节 组管理、用户管理、权限管理 / chmod /chown / umask / vim
三期第三讲1.组管理/用户管理(重要文件系统会实时备份 file-) vim/etc/group: 组管理文件://组名:密码控位键:组id:成员 vim/etc/gshadow:组密码管理文件:// ...
- deepin系统下安装git
1.打开命令行 2.输入 sudo apt-get update sudo apt-get install git 3.显示 建议安装: git-daemon-run | git-daemon-sys ...
- tomcat部署项目时省略项目名
大家也许知道在eclipse上通过新建server来部署项目到tomcat,并且通过server来管理项目的启动配置.server会自动创建启动该项目的xml 如: <Context docBa ...
- 初识QT
前言:这是写给纯小白看的文章,大神可以自行绕道. QT的优势(摘自360百科): Qt支持下列操作系统: Microsoft Windows 95/98, Microsoft Windows NT, ...
- 给yii架构的网站做Android客户端
网站未预留接口.给这类网站制作客户端就是模拟网页发送的post和get请求,然后获取服务器返回的数据. 1.在做客户端时先使用httpwatch分析浏览器发送的get和post请求的内容和URL.分析 ...
- thinkinginjava学习笔记04_初始化与清理
java沿用了c++的构造器,使用一个和类名完全一样的方法作为类的构造器,可以有多个构造器来通过不同的参数进行构造,称为重载:不仅是构造器可以重载,其他方法也一样通过不同的形参以及不同的返回值来实现重 ...
- CSS3的动画属性
transition.animation和transform是CSS3中三个制作动画的重要属性,本篇文章主要对其进行学习了解. 一.transition transition允许css的属性值在一定的 ...
- exports与module.exports,export与export default 之间的关系和区别
首先我们要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念. CommonJS模块规范 Node应用由模块组成,采用CommonJS模块规范. 根据这个规范,每个文件就是一个 ...
- Hive Getting Started补充
配置管理概述 Hive从<install-dir>/conf/hive-default.xml中读取它的默认配置 Hive配置目录的位置可以通过设置HIVE_CONF_DIR环境变量的值来 ...