在工作中写业务类通常都会重写hashCode与equals方法,而这两个方法的区别与用途也常常被问道。平时也只是大概知道这二者的用途,今天闲下来,查阅资料加上自己的理

解,总结记录下。

hashCode()与equals()方法都是从Object类中继承过来的

 public native int hashCode();
 public boolean equals(Object obj) {
return (this == obj);
}

其中hashCode 是java一个本地调用,实际上根据对象的地址来计算hashCode,而equals方法也是比较两个对象的地址值是否相同。一般而言,大部分类都自己重写实现了这

两个方法,equals一般用来比较两个对象的内容是否相同,而hashCode则用来比较对象的hash值是否相同。

1. 为什么要重写equals

在大部分情形中,如果一个对象的所有属性都是相同的,则认为这两个对象是相同的,但是Object中的equals方法比较的是对象地址值是否相同,这样就导致了new的两个对

象,虽然所有属性值都相同,但equals确实false,不符合业务。

<span style="white-space:pre">	</span>public class Student{

		private String name;

		private String sex;

		public Student(String name, String sex) {
super();
this.name = name;
this.sex = sex;
}
} @Test
public void test2(){
Student s1 = new Student("zhagnsan", "n");
Student s2 = new Student("zhagnsan", "n");
System.out.println(s1.equals(s2));
}

如上例,由于Student类没有重写equals方法,则导致在测试中s1.equals(s2)返回的是false,只要重写equals方法即可,重写后的equals方法比较的对象的属性值是否相同。

public class Student{

	private String name;

	private String sex;

	public Student(String name, String sex) {
super();
this.name = name;
this.sex = sex;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}
}

2. 为什么要重写hashCode

对象的hashCode的重写一般是用在HashMap,hashSet, hashTable等集合中,这些结构中是根据对象的hash值来确定对象的存储位置。如HashMap中的Key,hashMap中

不允许放入重复的键值,如果不重写key的hashCode,则会导致虽然两个key的值是一样的,但是是分别new出来的,内存地址是不一样的,这样hashCode()根据内存地址计

算出来的hash值也不一样,就能在hashMap中 存入键值相同的对象,违背了hashMap的设计规则。

还是以Student对象为例:

@Test
public void test3(){
Student s1 = new Student("zhagnsan", "n");
Student s2 = new Student("zhagnsan", "n");
System.out.println(s1.hashCode());
System.out.println(System.identityHashCode(s1));
System.out.println(s2.hashCode());
System.out.println(System.identityHashCode(s2));
}

输出的结果值为:

31170373
31170373
28678425
28678425

其中System.identityHashCode()方法返回的是根据对象的内存地址计算出来的hash值,可以看到如果没有重写hashCode方法,直接用Object对象的hashCode方法,与直接

用System.identityHashCode()计算出来的hash值是相同的。

接下来在Student对象中重写hashCode方法:

public class Student{

	private String name;

	private String sex;

	public Student(String name, String sex) {
super();
this.name = name;
this.sex = sex;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((sex == null) ? 0 : sex.hashCode());
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}

重新跑一遍测试,结果如下:

-1655006615
28678425
-1655006615
22440556

可以看到,虽然两个Student对象都是new出来的,但是调用对象的hashCode返回的hash值是相同的。

JDK规定,equals相等的两个对象hashCode值肯定相等,反之不一定。即hashCode值相等的两个对象,equals值可能相等,也可能不等。

记得在项目中有次出现多线程访问hashMap出现死循环的问题,然后查看了下其中hashMap的部分源码。发现hashMap存储结果是数组+链表来实现的。数组的位置为key的

hashCode的值,如果在该hash值的位置上已经有对象了,则遍历在这个位置上的链表,与链表的对象进行equals比较,如果存在相等的,在该对象已存在,如果不存在,在

在链表的末尾加上该对象。这里就表现成hashCode值相同的对象equals不一定相等。

equals一般用来比较对象的值(内容)是否相同,hashCode在常用在HashSet,HashMap,HashTable等结构中发挥在巨大作用。

hashCode与equals详解的更多相关文章

  1. hashCode、equals详解

    hash和hash表是什么? hash是一个函数,该函数中的实现就是一种算法,就是通过一系列的算法来得到一个hash值,这个时候,我们就需要知道另一个东西,hash表,通过hash算法得到的hash值 ...

  2. java中hashCode()与equals()详解

    首先之所以会将hashCode()与equals()放到一起是因为它们具备一个相同的作用:用来比较某个东西.其中hashCode()主要是用在hash表中提高 查找效率,而equals()则相对而言使 ...

  3. java中==和equals和hashcode的区别详解

    一.相同点 都是用来进行值或对象的比较. 二.不同点 对于“==”而言,对于基本类型(char,byte,short,int,long,float,double,boolean),对比的是值,所以是相 ...

  4. Java中 == 和 equals()详解

    java中的数据类型分为两种: 一 .基本数据类型: byte.short.int.long.float.double.char.boolean 比较它们需要用  ==  ,比较的是它们的值是否相等 ...

  5. ==和equals详解+例子

    一开始遇见==和equals我也是分不清,后来看了很多博客,收益匪浅, 担心以后给忘了,所以写下这个,以后复习可以用. (有哪里写得不对的,希望可以留言帮忙改进,大家一起共同进步) 一.Java数据类 ...

  6. 深入java面向对象一:==和equals详解

    本文从多篇博客笔记融合而来,系转载,非原创,参考: 1.  http://www.cnblogs.com/e241138/archive/2012/09/16/2687981.html 2.  htt ...

  7. java 中hashcode和equals 总结

    一.概述            在Java中hashCode的实现总是伴随着equals,他们是紧密配合的,你要是自己设计了其中一个,就要设计另外一个.当然在多数情况下,这两个方法是不用我们考虑的,直 ...

  8. [二] JavaIO之File详解 以及FileSystem WinNTFileSystem简介

    File类 文件和目录路径名的抽象表示形式. 我们知道,对于不同的操作系统,文件路径的描述是不同的 比如 windows平台:用\ linux平台:用/   File是Java为了这一概念提供的抽象描 ...

  9. Java提高篇——equals()与hashCode()方法详解

    java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...

随机推荐

  1. Laravel Repository 模式

    Repository 模式 为了保持代码的整洁性和可读性,使用Repository Pattern 是非常有用的.事实上,我们也不必仅仅为了使用这个特别的设计模式去使用Laravel,然而在下面的场景 ...

  2. nslookup命令详解

    Nslookup 是一个监测网络中DNS服务器是否能正确实现域名解析的命令行工具.它在 Windows NT/2000/XP(在之后的windows系统也都可以用的,比如win7,win8等) 中均可 ...

  3. python【第十九篇】Django进阶

    1.路由系统优化 1.1 路由分发 前面我们已经知道,在工程名下的urls.py中写我们的路由映射关系,那么问题来了,假设我们有10个app,如果把所有的url映射都写在urls.py文件中,那么每一 ...

  4. 【Python网络爬虫三】 爬去网页新闻

    学弟又一个自然语言处理的项目,需要在网上爬一些文章,然后进行分词,刚好牛客这周的是从一个html中找到正文,就实践了一下.写了一个爬门户网站新闻的程序 需求: 从门户网站爬取新闻,将新闻标题,作者,时 ...

  5. FFMPEG视音频编解码零基础学习方法-b

    感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...

  6. [转贴]JAVA:RESTLET开发实例(三)基于spring的REST服务

    前面两篇文章,我们介绍了基于JAX-RS的REST服务以及Application的Rest服务.这里将介绍restlet如何整合spring框架进行开发.Spring 是一个开源框架,是为了解决企业应 ...

  7. [收藏转贴]构建RESTful风格的WCF服务

    RESTful Wcf是一种基于Http协议的服务架构风格. 相较 WCF.WebService 使用 SOAP.WSDL.WS-* 而言,几乎所有的语言和网络平台都支持 HTTP 请求. RESTf ...

  8. 【Xamarin 跨平台机制原理剖析】

    原文:[Xamarin 跨平台机制原理剖析] [看了请推荐,推荐满100后,将发补丁地址] Xamarin项目从喊口号到现在,好几个年头了,在内地没有火起来,原因无非有三,1.授权费贵 2.贵 3.原 ...

  9. Earth to developers: Grow up!

    这是篇老外写的文章,主题是针对网络上的一些宗教式的争论,作者叙述了他自己的一些观点.主要从以下6点做了陈述.为了表达的精确性,就直接用英文. 1. Reject dogmatic thinking a ...

  10. ORACLE数字转换人民币大写

    ORACLE 数字转换人民币大写     示例.   数字                    :183066999230.68 人民币大写        :壹仟捌佰参拾亿陆仟陆佰玖拾玖万玖仟贰佰参 ...