您的位置:首页 > 编程语言 > Java开发

java中hashcode()和equals()的详解

2015-01-08 16:14 204 查看
下面是关于hashcode()和equals()的官方文档解释

hashCode

public int hashCode()

返回该对象的哈希码值。支持此方法是为了提高哈希表(例如
java.util.Hashtable
提供的哈希表)的性能。
hashCode
的常规协定是:

在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用
hashCode
方法都必须生成相同的整数结果。
如果根据
equals(java.lang.Object)
方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

返回:此对象的一个哈希码值。

equals

public boolean equals(Object obj)

指示其他某个对象是否与此对象“相等”。
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方法,两个对象比较会认为他们是同一个对象。

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: