java学习-- equals和hashCode的关系
hashcode的目的就是在hashset或者hashmap等中比较两个对象相等时,减少equals的使用次数来提高效率
以下为摘录
java中hashcode和equals的区别和联系
HashSet和HashMap一直都是JDK中最常用的两个类,HashSet要求不能存储相同的对象,HashMap要求不能存储相同的键。
那么Java运行时环境是如何判断HashSet中相同对象、HashMap中相同键的呢?当存储了“相同的东西”之后Java运行时环境又将如何来维护呢?
在研究这个问题之前,首先说明一下JDK对equals(Object obj)和hashcode()这两个方法的定义和规范:
在Java中任何一个对象都具备equals(Object obj)和hashcode()这两个方法,因为他们是在Object类中定义的。
equals(Object obj)方法用来判断两个对象是否“相同”,如果“相同”则返回true,否则返回false。
hashcode()方法返回一个int数,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。
接下来有两个个关于这两个方法的重要规范(我只是抽取了最重要的两个,其实不止两个):
规范1:
若重写equals(Object obj)方法,有必要重写hashcode()方法,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashcode()返回值。说得简单点就是:“如果两个对象相同,那么他们的hashcode应该 相等”。
不过请注意:这个只是规范,如果你非要写一个类让equals(Object obj)返回true而hashcode()返回两个不相等的值,编译和运行都是不会报错的。不过这样违反了Java规范,程序也就埋下了BUG。
规范2:
如果equals(Object obj)返回false,即两个对象“不相同”,并不要求对这两个对象调用hashcode()方法得到两个不相同的数。说的简单点就是:“如果两个对象不相同,他们的hashcode可能相同”。
根据这两个规范,可以得到如下推论:
1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。
2、如果两个对象不equals,他们的hashcode有可能相等。
3、如果两个对象hashcode相等,他们不一定equals。
4、如果两个对象hashcode不相等,他们一定不equals。
Java运行时环境是怎样判断HashSet和HastMap中的两个对象相同或不同?
先判断hashcode是否相等,再判断是否equals。
1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。 对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。
2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。 通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。
3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode。
4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。
5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。
有许多人学了很长时间的Java,但一直不明白hashCode方法的作用,我来解释一下吧。首先,想要明白hashCode的作用,你必须要先知道Java中的集合。
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。
你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。
但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。
如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。
这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
所以,Java对于eqauls方法和hashCode方法是这样规定的:
1、如果两个对象相同,那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同
上面说的对象相同指的是用eqauls方法比较。 你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降
下面是一个重写equals和hashcode的例子:
public class Cat
{
private String name;
private String birthday; public Cat()
{
} public void setName(String name)
{
this.name = name;
} public String getName()
{
return name;
} public void setBirthday(String birthday)
{
this.birthday = birthday;
} public String getBirthday()
{
return birthday;
} //重写equals方法
public boolean equals(Object other)
{
if(this == other)
{
//如果引用地址相同,即引用的是同一个对象,就返回true
return true;
} //如果other不是Cat类的实例,返回false
if(!(other instanceOf Cat))
{
return false;
} final Cat cat = (Cat)other;
//name值不同,返回false
if(!getName().equals(cat.getName())
return false;
//birthday值不同,返回false
if(!getBirthday().equals(cat.getBirthday()))
return false; return true;
} //重写hashCode()方法 //重写hashcode时用31 做因子 === 31 是2的5次方减一的素数;位移运算效率高,虚拟机对这方面的优化吧
public int hashCode()
{
int result = getName().hashCode();
result = * result + getBirthday().hashCode();
return result;
}
}
java学习-- equals和hashCode的关系的更多相关文章
- Java中equals()和hashCode()的关系以及重写equals()和hashCode()的重要性
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6580647.html 一:关系 如果两个对象相等(equal),它们的hashcode一定相同: 如果两个对 ...
- Java:重写equals()和hashCode()
Java:重写equals()和hashCode() 1.何时需要重写equals() 当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念). 2.设计equals() [1]使用instan ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
- Java中equals和hashcode的区别?
Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...
- java学习--equals
Object类是所有类的基类. Object类有equals方法.而继承Object中的equals方法判断的是两个对象的引用是否相等,相当于"==",也就是说只有比较的两个对象为 ...
- java中equals和hashCode方法的解析
解析Java对象的equals()和hashCode()的使用 前言 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个.在多 ...
- Java实战equals()与hashCode()
一.equals()方法详解 equals()方法在object类中定义如下: 代码 public boolean equals(Object obj) { return (this == obj); ...
- java的equals()与hashCode()以及包装类中的实现
1. hashcode 1.1 hashcode来源 1.2 hashcode的形式 1.3 hashcode目的 1.4 hashcode规则 1.5 hashcode作用体现 1.6 重写hash ...
- 【Java】equals()与hashCode()方法详解 (转)
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
随机推荐
- Sql Server索引重建
公司线上数据有几千万数据,有时候索引碎片会导致索引达不到我们的预期查询效率,这个时候将索引重建将会提升一定效率,不过重建的时候一定得晚上用户少的时候,索引重建需要一定时间. 直接贴自动重建索引脚本吧 ...
- Java错误:结束的字符文字
编译器为NetBeans 在学习java的时候突然出现了以下错误 错误代码是: Gen <Integer ,String> a = new Gen <Integer, String& ...
- java JDBC编程流程步骤
JDBC:Java Data Base Connection JDBC是用于运行sql语句并从数据库中获取新新的java API. JDBC是用来(让我们的程序)通过网络来操作数据库的,作用非常重要: ...
- 【Keil5 MDK】armar工具的基本用法(armar --help)
ARM Librarian, 5.03 [Build 76] - archive creation and maintenance tool Command format: armar options ...
- MySQL 5.7以上 root用户默认密码问题【转】
https://www.yanning.wang/archives/379.html 废话少说一句话系列: CentOS系统用yum安装MySQL的朋友,请使用 grep "temporar ...
- js中this是什么?
this是js的一个关键字 指定一个对象然后去替代他 分两种情况函数内的this和函数外的this 函数内的this指向行为发生的主体 函数外的this都指向window函数内的this跟函数在哪定义 ...
- 深入学习Motan系列(四)—— 客户端
困惑的袋鼠,对框架的把握有些茫然,但是仍然一步步向前,行动总比一直迷茫停止不前要好,您说呢,各位客官? 这篇开始客户端的分析.有些地方的代码,就不每段都标出了,中间有跳跃的地方,请自己对照代码来看.鄙 ...
- python函数之第一类对象
目录 python函数之第一类对象 python函数之第一类对象 第一类对象(英语:First-class object)在计算机科学中指可以在执行期创造并作为参数传递给其他函数或存入一个变数的实体. ...
- 在windows上使用ssh秘钥连接git服务器
git部署在centos7上 安装好git后,新建一个用户test(注意要加入git用户组)配置ssh秘钥登录,我的另一篇博客有写配置步骤 重点的地方是在windows系统上使用秘钥登录git服务器 ...
- Http协议基础及发展历史
一.网络分层协议 经典五层模型 1.物理层:(电脑的硬件,网卡端口,网线,网线连出去的光缆) 定义物理设备如何传输数据 2.数据链路层 在通信的实体间建立数据链路连接. 两台机器物理上是可以连接在一起 ...