2012-06-11 49 views
2

,作为人的定义:如何覆盖这个hashCode方法?

public class Person { 
    private int id; 
    private int characteristics; 
    public boolean equals (Object obj) { 
      if (obj == this) { 
       return true; 
      } 
      if (obj instanceof Person) { 
       if (id == ((Person) obj).id) { 
        return true; 
       } else if (characteristics == ((Person) obj).characteristics) { 
        return true; 
       } 
      } 
      return false; 
    } 
} 

原因2个Person对象ab必须有相同的哈希码,如果a.equals(b)回报true,应该怎么实现hashCode方法?

解决方案

equals方法实现,根据Java的等效协议是不正确的:传递不满意:a.id = 1a.characteristic = 2b.id = 1b.characteristic = 3c.id = 2c.characteristic = 3; a.equals(b) == trueb.equals(c) == true,但是a.equals(c) == false

+1

您可以异或ID和特征变量。 –

+0

为了记录,您可以将第二组这些“if”转换为回报,即。 'return obj instanceof Person &&(id ==((Person)obj).id || characteristics ==((Person)obj).characteristics);'。你还应该在当前代码的末尾注意'return false',因为你的'equals'方法可能不会返回任何东西。 – SimplyPanda

+3

@SimplyPanda第一个是完全错误的。 'return obj == this;'如果'obj'不是相同的实例,将会返回false,但是可能仍然是相等的值。 – cdhowie

回答

5

由于类认为当任其各自idcharacteristics字段都是相等的对象相等,则可以合理利用这里唯一的哈希码是所有的恒定值实例:

public int hashCode() { 
    return 0; 
} 

这将使基于散列的查找性能非常糟糕。

equals()中的任一个或者测试通常是一个坏主意;对象实际上不是等于,是吗?也许他们只是一个“匹配对方?”也许你应该考虑单独离开equals()并执行一些其他比较方法。


由于Thomasz指出的那样,你equals()测试不传递;如果a.equals(b) && b.equals(c)为真,则a.equals(c)必须为真。这是而不是与您的超负荷一致,因此您的实施违反equals()的合同。我强烈建议您以不同的方法实施此测试,并且只保留equals()

+2

这是正确的答案:)(等于set/collections是好的,只是hashcode在OP的情况下不起作用) – bestsss

1

这是你的类什么自动生成:

@Override 
public int hashCode() { 
    int result = id; 
    result = 31 * result + characteristics; 
    return result; 
} 

而经过几年的重构:

@Override 
public int hashCode() { 
    return 31 * id + characteristics; 
} 

并记录在案,只是我还是你的equals()坏了?如果id s或characteristics相等,但不一定是两者,则认为两个对象相等。这意味着你的平等不是传递一旦你的对象进入荒野,这可能会有真正意想不到的副作用。

这里是一个体面的实现:

@Override 
public boolean equals(Object o) { 
    if (this == o) { 
     return true; 
    } 
    if (!(o instanceof Person)) { 
     return false; 
    } 

    Person person = (Person) o; 
    return characteristics == person.characteristics && id == person.id; 
} 
+1

这似乎不是完全对我来说,不是OP的equals()方法指示if(id == person.id)|| (特征== person.characteristics) – NominSim

+0

YES:'if(id == person.id)|| (特征== person.characteristics)' –

+0

@NominSim:你是对的。然而,由OP定义的'equals()'不是可传递的,我的'hashCode()'对正确的'equals()'有效 - 我后来才注意到。我接受你谦虚的downvote,但我相信OP有更大的问题,然后... –

0

如果具有相同id意味着始终具有相同characteristics(您equals()是有效的,这似乎有必要),那么你的哈希代码可以使用characteristics独自:

@Override 
public int hashCode() { 
    return characteristics; 
} 

如果不是的话,你@cdhowie建议,可能要重新考虑使用Java平等来表达这种关系。