黑马程序员技术交流社区
标题:
equals小疑问
[打印本页]
作者:
我自信我很牛
时间:
2013-3-16 20:54
标题:
equals小疑问
本帖最后由 烟磊磊 于 2013-3-16 23:53 编辑
在重写equals方法时,为什么要重写hashcode,最好解释一下,最好能解释一下,在内存中hashcode是怎么用的。
作者:
杨博
时间:
2013-3-16 20:56
public int hashCode()返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常规协定是:
在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
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。
LZ可以参考下
作者:
郝强勇
时间:
2013-3-16 21:56
重写equals不一定要重写hashcode方法,之所以重写hashcode方法,是防止自定义对象在存入HashSet或是HashMap集合的时候,要保证对象唯一性的判断依据而已。这个是底层的调用过程,每次存入的对象(第一个除外)都会先调用hashcode方法进行比较,如果不一致直接存入集合,如果hashcode相同的话,就在比较equals方法。
其实hashcode和equals方法的方法体是我们自己定义的,换句话说,比较方式(依据)是我们自己定义的。
(主要记住先执行hashcode方法在执行equal方法,对啦,这些方法都是自动被调用的,就够啦)
作者:
黄玉昆
时间:
2013-3-16 23:05
只有类的实例对象要被采用哈希算法进行存入和检索时,这个类才需要按要求复写hashCode()方法,即使程序可能暂时不会用到当前类的hashCode()方法,但是为提供一个hashCode()方法也不会有什么不好,没准以后什么时候就会用到这个方法,所以通常要求hashCode()和equals()两者一并被覆盖。简单来说,就是默认的hashCode()方法可能不是我们需要的,而且这种算法可能会导致两个不同的对象获得的哈希值会相同,那么就会产生意想不到的结果,所以需要覆写hashCode()方法。
需要注意的是,当对象每次调用方法时,会先调用hashCode()的方法:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class ReflectTest2 {
public static void main(String [] args){
Collection cons = new HashSet();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
cons.add(pt1);
cons.add(pt2);
cons.add(pt3);
cons.add(pt1);
cons.remove(pt1);
System.out.println(cons.size());
}
}
public class ReflectPoint {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
//System.out.println("demo...");//测试
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
public String toString(){
return str1+";" + str2 + ";" + str3;
}
}
复制代码
你把测试的那个注释打开,你就看到现象了。
作者:
IT菜鸟
时间:
2013-3-16 23:37
HashCode 和equals 方法都从Object 继承的方法,在没有重写的情况下,这两者比较 的都是对象的地址。我们在往HashSet或是HashMap集合的时候放对象的时候,判断这两个对象是否相等,是先判断 hashCode 是否相等,如过不等则直接存入,如果hashcode 相等,再判断equals 是否相等,equals相等,则表示是同一个对象。不在 存入。如果不等则存入对象。但是在实际的应用中,我们判断两个对象,是否相等,需要判断的是内容,而不是地址,因此要重写equals。但是根据判断规则,它先判断的是hashCode 而不是equals.在hashCode 不同的情况下,就直接存入了,不再调用equals 了,因此,为了达到,我们比较内容的目标,重写equals 方法的时候,最好重写hashCode 已达到我们正确的比较结果。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2