Java Enthuware示例-哈希代码和等于

Java Enthuware示例-哈希代码和等于,java,generics,collections,scjp,Java,Generics,Collections,Scjp,我正在做一些来自Enthuware模拟器的示例问题。下面是一个示例问题 public class GoodOne { int theval; public int hashCode() { return theval%3; } public boolean equals(Object obj) { try{ // 1 insert code here. }catch(Exception e) {

我正在做一些来自Enthuware模拟器的示例问题。下面是一个示例问题

public class GoodOne
{
   int theval;
   public int hashCode()
   {
      return theval%3;
   }
   public boolean equals(Object obj)
   {
      try{
      // 1 insert code here.
      }catch(Exception e) {
        return false;
      }
   }
}
选项如下所示

  • 返回true
  • 返回this==obj?真:(theval%3==0&((GoodOne)obj)。theval%3==0)?真:假
  • 返回值%2==0?真:假
  • return((int)Math.random())*10%3==0?真:假。
    假设Math.random()返回一个介于0.0和1.0(不包括1.0)之间的double
  • 返回false
  • 模拟器选择的正确答案是选项2,并给出了该解释

    这意味着,如果对象的
    值%3
    为 0此外,如果确定两个对象相等,则它们的哈希代码(
    theval%3
    )将始终相同(零)。所以它满足了 hashCode和equals方法的要求

    要记住的规则是:如果
    equals()
    方法返回true,则 两个对象的
    hashCode()
    必须相同。反之亦然 可取但不必要

    此外,equals方法必须遵循以下规则:它应该 自反:对于任何参考值x,
    x.equals(x)
    应返回true。 它应该是对称的:对于任何参考值x和y,
    x.equals(y)
    当且仅当
    y.equals(x)
    返回true时,应返回true。它应该 可传递:对于任何参考值x、y和z,如果
    x等于(y)
    返回true和
    y.equals(z)
    返回true,然后
    x.equals(z)
    应该 返回true。它应该是一致的:对于任何参考值x和 y、 多次调用
    x.equals(y)
    始终返回true或 如果没有在equals中使用信息,则始终返回false 修改对象上的比较。对于任何非空引用 值x,
    x.equals(null)
    应返回false

    选项1是错误的,因为它将导致所有对象 被认为是相等的,因此
    hashCode()
    必须返回相同的值 所有对象的值,情况并非如此

    选项2是正确的,因为所有3的倍数都是 0因此,如果我们在
    equals()
    方法中为3的所有倍数返回true,则该条件将得到满足。如果 对象与自身进行比较

    选项3不正确,因为将考虑2和6 相等,但它们的哈希代码将不同(2和0)

    选项4是错误的,因为我们无法确定哪些对象将被删除 被认为是平等的

    我无法理解它的解释。有人能解释一下为什么选项2是正确的吗 在这个样本中。谢谢

    选项2是正确的,因为3的所有倍数的hashCode()都是0。因此,如果我们在equals()方法中为所有3的倍数返回true,则该条件将得到满足。如果将对象与自身进行比较,它也会返回true

    嗯,我必须说,这是一个可怕的解释,有利于为什么这一选择的工作。可能是因为,
    equals()
    hashCode()
    方法本身的实现很糟糕。当前,如果两个对象具有相同的hashcode(某种程度上),则
    equals()
    方法返回true。让我们再看看这个部分:

    return this == obj? true : (theval%3 == 0 && ((GoodOne)obj).theval%3==0) ? true :false;
    
    首先,该表达式可以改进为(尽管这也不是一个好的实现):

    现在,
    val%3
    只不过是该对象的哈希代码。所以,基本上,这个方法是根据两个对象的哈希码来判断它们是否相等。(好吧,
    hashCode()
    方法也不是一个好的实现示例)

    equals()
    方法的一个大问题是,它不处理
    null
    。天哪。我建议停止阅读该资源,您将其命名为什么-Enthuware。

    话虽如此,这个equals方法在与给定的hashcode协作时可以很好地工作(前提是,
    null
    被正确处理)。如何,让我们考虑<代码>等于方法:

    • 反身:那很好<代码>a.theVal%3==a.theVal%3
    • 对称:这也很好。对于两个对象
      a
      b
      ,如果
      a.theVal%3==b.theVal%3
      ,则反之亦然
    • 及物性-这也很好
      a.theVal%3=b.theVal%3
      b.theVal%3==c.theVal%3
      ,表示
      a.theVal%3==c.theVal%3
    • 一致-如果
      a.theVal%3==b.theVal%3
      ,那么如果
      a.theVal
      b.theVal
      均未更改,则始终是这样
    现在是
    equals()
    hashCode()
    之间的契约:

    • 如果两个对象相等,则它们的哈希代码必须相等。这在这里肯定是正确的,因为您已经在根据哈希代码判断对象是否相等
    因此,这就解释了第二个选项在这里的作用


    你应该记住的是: 需要记住的一点是,您应该使用相同的一组对象属性来计算用于判断对象相等的哈希代码,否则契约将破裂

    例如,如果您的类中还有一个字段,请说-
    name
    ,并且您的
    hashCode
    方法更改为:

    theVal % 3 * name.hashCode();
    
    但是您没有更改
    equals()
    方法。然后,如果两个对象具有相同的
    val
    值,但名称不同,则根据
    equals()
    方法实现,它们将相等,但鉴于上述
    hashCode()
    的实现,它们的hashCode将不同


    更好的equals()和hashCode()? 我说过,给定的
    hashCode()theVal % 3 * name.hashCode();