下面是关于hashcode()和equals()的官方文档解释
hashCode
-
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如
java.util.Hashtable
提供的哈希表)的性能。hashCode
的常规协定是:- 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
- 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用
hashCode
方法都必须生成相同的整数结果。 - 如果根据
equals(java.lang.Object)
方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
-
-
返回:
- 此对象的一个哈希码值。
equals
-
指示其他某个对象是否与此对象“相等”。
equals
方法在非空对象引用上实现相等关系:- 自反性:对于任何非空引用值
x
,x.equals(x)
都应返回true
。 - 对称性:对于任何非空引用值
x
和y
,当且仅当y.equals(x)
返回true
时,x.equals(y)
才应返回true
。 - 传递性:对于任何非空引用值
x
、y
和z
,如果x.equals(y)
返回true
,并且y.equals(z)
返回true
,那么x.equals(z)
应返回true
。 - 一致性:对于任何非空引用值
x
和y
,多次调用 x.equals(y) 始终返回true
或始终返回false
,前提是对象上equals
比较中所用的信息没有被修改。 - 对于任何非空引用值
x
,x.equals(null)
都应返回false
。
Object
类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值x
和y
,当且仅当x
和y
引用同一个对象时,此方法才返回true
(x == y
具有值true
)。注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
- 自反性:对于任何非空引用值
-
-
参数:
-
obj
- 要与之比较的引用对象。
返回:
-
如果此对象与 obj 参数相同,则返回
true
;否则返回false
。 -
-
1、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
2、如果两个对象相同(及两个对象的地址值相同),就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;
3、如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;
4、两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个桶里”。
5、两个对象的 hashCode不同,则equals(java.lang.Object) 一定不同。本段摘自互联网
1.hashcode是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有
例如内存中有这样的位置
0 1 2 3 4 5 6 7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除 8求余数直接找到存放的位置了。
2.但是如果两个类有相同的hashcode怎么办呢(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊
看下面的例子:
package com.java.hashcode;
public class hashcode {
int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int hashCode() {
// 重新hashcode方法 hashcode值相同。
return this.id;
}
public hashcode() {
}
}
客户端
package com.java.hashcode;
import java.util.HashSet;
public class hashcodeTest {
/**
* @param args
*/
public static void main(String[] args) {
HashSet<hashcode> ha=new HashSet<hashcode>();
hashcode a = new hashcode();
hashcode b = new hashcode();
a.setId(1);
b.setId(1);
System.out.println(a.hashCode()==b.hashCode());//hashcode值相同
System.out.println(a.equals(b));//hashcode值相同,但是两个对象不相等。我们没有重写object的equal方法,所以会调用默认的equals方法,比较两个对象的
//地址值,发现不是同一个对象
ha.add(a);
ha.add(b);
System.out.println(ha);//默认的是getClass().getName() + '@' + Integer.toHexString(hashCode()),类名+@+hashcode值
/**
* 运行结果:
* true
false
[com.java.hashcode.hashcode@1, com.java.hashcode.hashcode@1]
hashset里面包含相同的对象,显然这个不符合hashset的定义,下面我们就要重新定义equals方法。
*/
}
}
下面重新定义equals方法:
package com.java.hashcode;
public class hashcode {
int id;
String name;
int[] array;//思考一下?我们定义了,name 字段和一个整形数组 equals是时候该怎么样比较? 是比较他们的存储地址?还是比较他们的值?数组又该如何去比较?
//我觉得应该是比较他们的值,你觉得呢? 但是数组比较就会很麻烦,记得原来学习集合框架的时候,hashset中最好是添加固定不变的对象,像这种有不确定值
//的对象,比较的确好麻烦啊
public int[] getArray() {
return array;
}
public void setArray(int[] array) {
this.array = array;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int hashCode() {
// 重新hashcode方法 hashcode值相同。
return this.id;
}
public hashcode() {
}
@Override
public boolean equals(Object obj) {
if(obj==null){
return false;
}
if(obj==this){
return true;
}
if (obj instanceof hashcode) { //obj和this是同一类对象,看属性值是否相同
hashcode hs = (hashcode) obj;
if (hs.id == this.id) {
return true;
}
}
return false;
}
}
客户端:
package com.java.hashcode;
import java.util.HashSet;
public class hashcodeTest {
/**
* @param args
*/
public static void main(String[] args) {
HashSet<hashcode> ha = new HashSet<hashcode>();
hashcode a = new hashcode();
hashcode b = new hashcode();
a.setId(1);
b.setId(1);
System.out.println(a.hashCode() == b.hashCode());// hashcode值相同
System.out.println(a.equals(b));// hashcode值相同,但是两个对象不相等。调用我们重写object的equal方法。
ha.add(a);
ha.add(b);
System.out.println(ha);// 默认的是getClass().getName() + '@' +
// Integer.toHexString(hashCode()),类名+@+hashcode值
// 运行结果:
// true
// true
// [com.java.hashcode.hashcode@1]
// 调用我们覆盖的父类的equals方法,两个对象比较会认为他们是同一个对象。
}
}