平时使用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()的更多相关文章

  1. 【Java】hashcode()和equals()

    大家知道,在集合中判断集合中的两个元素是否相同,依赖的是hashcode()和equals()两个方法. > 一个简单的实验 public class Teacher { private Int ...

  2. 【Java】 hashcode()和System.identityHashCode()

    hashcode()和System.identityHashCode() openjdk8: http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/5b86f ...

  3. 【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 ...

  4. 【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 ...

  5. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  6. 【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 ...

  7. 【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 ...

  8. 【Java】 子字符串的比较(substring的==与equal()使用)

    public class Test { public static void main(String[] args) { String str1="good"; System.ou ...

  9. 【Java】代理模式,静态代理和动态代理(基于JDK或CGLib)

    当我们需要在一个方法之前或之后添加一段逻辑时,自然会想到使用代理类.代理类帮我们代理了实际类的调用,然后可以在实际调用之前和之后添加一些逻辑,从而不浸入实际类. 拓展:由于代理类能在实际类调用之前和之 ...

随机推荐

  1. Xamarin Android自定义文本框

    xamarin android 自定义文本框简单的用法 关键点在于,监听EditText的内容变化,不同于java中文本内容变化去调用EditText.addTextChangedListener(m ...

  2. 我是如何确认线上CLOSE_WAIT产生的原因及如何解决的。

    1.阐述 内部架构:Tomcat应用程序---> nginx ---> 其他Tomcat应用程序,内部Tomcat应用通过nginx调用其他应用. HTTP插件:HttpClient 4. ...

  3. 安装Linux桌面后无法显示登录桌面

    安装完图形后无法显示图形界面,只有命令行模式界面 . 猜测原因可能跟电脑位有关,在BIOS中开启虚拟化技术, 电脑开启设置F2 /Security/Virtualization, 选择Enable. ...

  4. 阅读MDN文档之CSS选择器介绍(一)

    本文为阅读MDN文档笔记 目录 Different types of Selectors Attribute Selectors Presence and value attribute select ...

  5. UNIX域协议(无名套接字)

    关于什么是UNIX域套接字可以参考:http://www.cnblogs.com/xcywt/p/8185597.html这里主要介绍非命名的UNIX域套接字的用法.1.socketpair函数先看m ...

  6. [编织消息框架][netty源码分析]12 ByteBuf 实现类UnpooledDirectByteBuf职责与实现

    public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { private final ByteBufAl ...

  7. Kafka的基本概念与安装指南(单机+集群同步)

    最近在搞spark streaming,很自然的前端对接的就是kafka.不过在kafka的使用中还是遇到一些问题,比如mirrormaker莫名其妙的丢失数据[原因稍后再说],消费数据offset错 ...

  8. 解决反序列化(Deserialize)无法找到程序集的错误

    http://blog.csdn.net/w_s_q/article/details/5677536 在使用.NET序列化对象时,会将程序集信息也包含进去.如果将序列化之后的字节数组通过网络(或其他传 ...

  9. Ubuntu安装微信

    1.系统是Ubuntu 16.04 64位系统,在网上先去下载electronic-wechat-Linux         https://github.com/geeeeeeeeek/electr ...

  10. windows10合并分区

    删除无用分区 将分区D合并到分区C,"计算机"---右键"管理"--"磁盘管理" 点击分区名,右键选择删除卷,如果有数据,提前备份 扩展分区 ...