下面是关于hashcode()和equals()的官方文档解释
java.util.Hashtable
提供的哈希表)的性能。
hashCode
的常规协定是:
hashCode
方法都必须生成相同的整数结果。equals(java.lang.Object)
方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
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
- 要与之比较的引用对象。
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方法,两个对象比较会认为他们是同一个对象。 } }