簡體   English   中英

為什么this == other和this.hashcode == other.hashcode()給出不同的結果?

[英]Why are this == other and and this.hashcode == other.hashcode() giving different results?

我有一個帶有以下equals()hashCode()方法的類

@Override
public boolean equals(Object o)
{
  if (this == o) { return true; }
  if (o == null || getClass() != o.getClass()) { return false; }

  Phrases that = (Phrases) o;

  if (this.hashCode() == o.hashCode()) { return true; } //retry clover coverage test
  if (exitMsg != null ? !exitMsg.equals(that.exitMsg) : that.exitMsg != null)
  { return false; }
  if (introMsg != null ? !introMsg.equals(that.introMsg) : that.introMsg != null)
  { return false; }
  if (msg != null ? !msg.equals(that.msg) : that.msg != null)
  { return false; }
  if (phrase != null ? !phrase.equals(that.phrase) : that.phrase != null)
  { return false; }
  if (title != null ? !title.equals(that.title) : that.title != null)
  { return false; }

  return true;
}

@Override
public int hashCode()
{
  int result = phrase != null ? phrase.hashCode() : 0;
  result = 31 * result + (title != null ? title.hashCode() : 0);
  result = 31 * result + (introMsg != null ? introMsg.hashCode() : 0);
  result = 31 * result + (msg != null ? msg.hashCode() : 0);
  result = 31 * result + (exitMsg != null ? exitMsg.hashCode() : 0);
  return result;
}

我試圖弄清楚為什么三葉草不能說我的哈希碼方法已經運行了。 我添加了一行:

if (this.hashCode() == o.hashCode()) { return true; } //retry clover coverage test

根據三葉草,每次此equals方法都運行if (this == o) { return true; } if (this == o) { return true; }假,if (this.hashCode() == o.hashCode()) { return true; } if (this.hashCode() == o.hashCode()) { return true; }正確的


題:

為什么this == othis.hashCode() == o.hashCode()不能以相同的結果求值?

根據定義,哈希碼包含的信息少於源數據。 這意味着可能發生沖突,在這種情況下,您將擁有兩個具有相同哈希碼但不相等的對象。

Java hashCode()的一般要求是相反的:

  • equals關系成立的兩個對象必須產生相同的哈希碼(反之則不成立)
  • 如果兩個對象不同,則根本不需要它們產生不同的哈希碼

基本上,關鍵是您不能將哈希碼用作唯一標識符 (實際上,JDK數據結構在內部管理沖突)。

這與==無關,因為它只比較對象的引用(內存地址),對於它們的hashCode()和equals幾乎相同。

如果查看一下hashCode()您會發現,如果除了一個字段之外的所有字段都為空,但哪個字段不同,則所計算的哈希碼是相同的,這清楚地證明了您可以輕松生成沖突的事實。

如果您想要更強大的功能,則應考慮使用MessageDigest ,它產生的摘要要比int長得多(因此,能夠容納更多信息=發生碰撞的可能性較小)。 但是即使有了它們,您也無法保證。

==不調用.equals

實際上,兩者是完全不同的,僅在未覆蓋Object的默認(不良)實現的對象中重疊。

==只是檢查太對象是否是等效的指針。

.equals運行與您顯示的方法類似的方法。

.equals替換==應該可以解決您的問題

退后一步...

考慮equals()hashCode()的協定。 考慮一下契約僅是一種方式的事實:如果您同時在一個類中實現這兩種協議,那么要求是,如果一個類的兩個實例相等,則它們必須具有相同的哈希碼。

它沒有說的是,如果兩個實例具有相同的哈希碼,則它們必須相等。 但是,您假設在您的.equals()實現中!

但是在您的代碼中,有:

// WRONG!
if (this.hashCode() == o.hashCode()) { return true; }

這是一個完全有效的hashCode()方法的示例:

public int hashCode()
{
    return 42;
}

現在,我相信您可以通過.equals()方法查看問題所在。


假設使用Java 7,這是編寫兩種方法的方式。 因為兩者都考慮了null ,所以這很容易(另一方面,應盡可能避免使用null ;最終, null只是麻煩而已):

@Override
public final int hashCode()
{
    return Objects.hash(phrase, title, introMsg, msg, errorMsg);
}

@Override
public final boolean equals(final Object obj)
{
    if (obj == null)
        return false;
    if (this == obj)
        return true;
    if (getClass() != obj.getClass())
        return false;
    final MyClass other = (MyClass) obj;
    return Objects.equals(phrase, other.phrase)
        && Objects.equals(title, other.title)
        && Objects.equals(introMsg, other.introMsg)
        && Objects.equals(msg, other.msg)
        && Objects.equals(errorMsg, other.errorMsg);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM