java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析
1、Object类中的equals方法和hashCode方法。
Object类中的equals和hashCode方法简单明了,所有的类都继承了这两个方法,只是有些类(String、Integer等)会重写这两个方法实现自己的更详细功能,之后会重点介绍。
① equals():
1
2
3
|
public boolean equals(Object obj) { return ( this == obj); } |
②hashCode():
1
|
public native int hashCode(); |
1
|
|
1
|
equals方法比较两个对象的引用(地址)是否相等,hashCode调用的是本地的方法,实质上对象调用hashCode方法返回的是对象引用(地址)的值。这样若equals方法返回为 true ,这两个引用一定是相等的,hashCode方法返回的值也就是相等的。 |
1
|
|
1
|
|
1
|
<SPAN style= "FONT-SIZE: medium" ><STRONG> 2 、其他类中重写的equals方法和hashCode方法。</STRONG></SPAN> |
1
|
|
1
|
java类库中很多类都重写了Object中的这两个方法,实现了自己更详细的功能,比如String类中重写equals之后,保证了即使对象引用不同,但是字符串的内容相同,也同样返回为 true ,也被认为是两个字符串对象是相等的,这在语义上也更符合人类的思维.比如: |
1
2
3
4
|
String str1 = new String( "abc" ); String str2 = new String( "abc" ); System.out.println(str1.equals(str2)); //返回true System.out.println(str1 == str2); //返回false |
1
|
|
1
|
|
1
|
在这段代码中str1 和 str2 是保存的不同的引用的,但是字符串的内容是相同的,都是“abc”(其实“abc”在String类中是以字符数组保存的,喜欢看java源代码,了解类的内部实现的童鞋应该很了解吧,推荐大家在用一个类的时候多看它的源代码,很多实现的原理都可以找到,并且能够学到很棒的类的设计和算法的实现-_-)。使用 == 比较的则是两个地址是否相等,当然返回的是 false .但是使用String类中重写的equals方法便能够判断两个对象内部的字符串是相同的,也理所当然的返回 true . |
1
|
|
1
|
下面给出String类中这两个方法的实现: |
1
|
|
1
|
①equals(): |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public boolean equals(Object anObject) { if ( this == anObject) { return true ; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0 ; while (n-- != 0 ) { if (v1[i] != v2[i]) return false ; i++; } return true ; } } return false ; } |
1
|
②hashCode(): |
1
2
3
4
5
6
7
8
9
10
11
12
|
public int hashCode() { int h = hash; if (h == 0 && value.length > 0 ) { char val[] = value; for ( int i = 0 ; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; } |
1
|
|
1
|
从上面两个方法我们可以了解到很多东西,equals方法首先判断了两个引用是否相等,如果相等直接 return true ,这是必须的,引用都相等了肯定是同一个对象.如果引用不相等,并没有结束,而是继续判断是不是String类的实例,如果是,检测对象中字符串数组的每一个元素是否相同,如果相同那么就返回 true ,判定为相等。 |
1
|
|
1
|
在看hashCode方法,String类中也重写了hashCode方法,其中返回一个 int 型数据,可以看出是根据字符串数组中的元素计算出来的一个值。试想一下,如果equals方法返回为 true ,那说明这个String对象里面的内容是一样的,hashCode方法根据内容计算的返回的值也当然是相同的了。 |
1
|
|
1
|
不知各位发现了没有, 对于equals返回为 true 的两个对象,hashCode方法返回的值也一定是相同的(对于Object类,equals返回 true 表示地址相同,hashCode正好是返回地址,必定相同。对于String类,equals返回 true 表示内容相同,hashCode根据内容返回一个值,也必定是相同的)。 |
1
|
|
1
|
但是反过来成立么,对于hashCode返回值相同的对象,equals返回一定是 true 吗?思考一下,答案是否定的。因为String类中的hashCode是根据字符数组的元素经过一系列复杂计算得出的,会不会有这种情况,hashCode的返回值相同,但是字符串的内容错位差那么一点(就是字符串的元素不完全相同,但是经过计算恰好保证了hashCode相同),这点概率还是有的。所以上面的那句话是不成立的,这里可能有点难以理解,静下心来仔细想想. |
1
|
|
1
|
再来一句话,hashCode返回值不同的对象,equals返回一定是 false ,对否? ……这个通过上面的红字应该可以推理得到吧。hashCode返回不同,但是equals返回为 true ,可能吗..equals返回为 true ,hashCode就一定相等了好么亲爱的。所以这句话是对的。 |
1
|
|
1
|
我们还应该注意,Java语言对equals()的要求如下,这些要求是必须遵循的: |
1
|
|
• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
• 反射性:x.equals(x)必须返回是“true”。
• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
• 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
• 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
通过上面的分析,可以得出一个重要的类设计思想,equals方法返回为true的两个对象,一定要保证hashCode返回值相等。Object类中保证了,String类中保证了,大家可以去看Double类,Integer类就会返现,都保证了这一点,hashCode都是与内容有关的。在自己编码设计类的过程中,如果要重写equals方法,进行自己的必要,也要注意同时重写Object的hashCode方法,保证这一点。
上实例,要求设计一个Student类,重写equals方法和hashCode方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
class Student { int num; String name; Student( int num, String name) { this .num = num; this .name = name; } public int hashCode() { return num * name.hashCode(); } public boolean equals(Object o) { if ( this == o) { return true ; } Student s = (Student) o; return num == s.num && name.equals(s.name); } public String toString() { return num + ":" + name; } } |
看上面这个例子是否能够满足前面谈到的要注意的几点?
若两个Student对象学号和名字一样能否返回true?
若equals方法返回true,hashCode返回值是否相等?
总结:①Object类中有自己的equals和hashCode方法,String等类进行了重写,可以判断内容是否真正相等。
②重写equals方法必须同时重写与之相配的hashCode方法。
③equals返回为true的两个对象,hashCode返回的值必须是相同的。
④hashCode返回值相同,equals不一定返回true。
⑤hashCode返回值不相同,equals一定返回的是false。
谈到这两个方法不得不提到集合类中Hash那一辈,下一篇博文将详细讲解和理清集合类中是如何通过这两个方法,保证集合中的元素不重复的,会利用hashCode方法和equals方法从内部了解其中比较的技巧.
java中equals和hashCode方法随笔二的更多相关文章
- java中equals和hashCode方法的解析
解析Java对象的equals()和hashCode()的使用 前言 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个.在多 ...
- Java中equals和hashcode的区别?
Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...
- java重写equals和hashCode方法
一.重写equals方法 如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等. 利用equals比较八大包装对象(如int,f ...
- Java中equals,hashcode
在Java语言中,Object对象中包含一个equals和hashCode方法,其中hashCode方法是由JVM本地代码(native code)实现的,返回值是一个有符号的32位整数,对 ...
- 【Java】equals()与hashCode()方法详解 (转)
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- Java中equals()和hashCode()的关系以及重写equals()和hashCode()的重要性
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6580647.html 一:关系 如果两个对象相等(equal),它们的hashcode一定相同: 如果两个对 ...
- java中equals与hashCode的重写问题
这几天有一个朋友问我在重写equals和hashCode上出现了问题,最后我帮她解决了问题,同时也整理出来分享给大家 现上Object的equals与HashCode的代码 public boolea ...
- Java 重写equals()与hashCode()方法
List对象的contains方法实际上也是调用的equals()方法来进行逐条对比的. 示例代码: package com.imooc.collection; /** * 课程类 */ public ...
- Java中equals,hashcode,==的区别
== :比较java栈局部变量表中变量的地址或值是否相等. equals : 比较变量的地址在java堆中引用对象是否为同一个对象. hashcode : 通过对象在JVM内存中的存储地址通过特定算 ...
随机推荐
- SQL Server数据库log shipping 灾备(Part1 )
1.概述 Log Shipping为SQL Server提供的数据库备份过程.它可以将数据库整个复制到另一台服务器上.在这种情况下,交易日志也会定期发送到备份服务器上供恢复数据使用,这使得服务器一直处 ...
- SQL Server 2012安装配置(Part3 )
SQL Server 2012安装配置(Part1 ) SQL Server 2012安装配置(Part2 ) SQL Server 2012安装配置(Part3 ) 3 客户端安装 3.1 安装客户 ...
- 使用代码获得Netweaver里某个software component和C4C的版本
有同事问如何通过代码的方式获得Netweaver里某个Software component的版本信息,以及Cloud for Customer(C4C)的版本信息. Netweaver 点了Detai ...
- 卓越管理的实践技巧(3)推动团队管理的要点 Facilitation Essentials for Managers
Facilitation Essentials for Managers 前文卓越管理的秘密(Behind Closed Doors)最后一部分提到了总结的13条卓越管理的实践技巧并列出了所有实践技巧 ...
- Oracle CRS/GI 进程介绍
在10g和11.1,Oracle的集群称为CRS(Oracle Cluster Ready Service), 在11.2,Oracle的集群称为GI(Grid Infrastructure). 对于 ...
- python_105_类的特殊成员方法
aa.py class C(): def __init__(self): self.name='QiZhiguang' 类的特殊成员方法: # 1. __doc__ 表示类的描述信息 class Do ...
- sklearn 学习之分类树
概要 基于 sklearn 包自带的 iris 数据集,了解一下分类树的各种参数设置以及代表的意义. iris 数据集介绍 iris 数据集包含 150 个样本,对应数据集的每行数据,每行数据包含 ...
- DROP OPERATOR - 删除一个操作符
SYNOPSIS DROP OPERATOR name ( lefttype | NONE , righttype | NONE ) [ CASCADE | RESTRICT ] DESCRIPTIO ...
- ssh整合思想初步 struts2与Spring的整合 struts2-spring-plugin-2.3.4.1.jar下载地址 自动加载Spring中的XML配置文件 Struts2下载地址
首先需要JAR包 Spring整合Structs2的JAR包 struts2-spring-plugin-2.3.4.1.jar 下载地址 链接: https://pan.baidu.com/s/1o ...
- vuePress的使用
今天来玩一玩vuePress的使用,用markdown来编辑一个页面网站,这里谈论到了简单使用,细节可以去官网上去查看 开始安装 项目依赖 // package.json { "name&q ...