簡體   English   中英

Hashcode()Vs Equals()

[英]Hashcode() Vs Equals()

我有兩個以下的課程..

class Emp //implements Comparable
{
      String name,job;
      public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    int salary;
      public Emp(String n,String j,int sal)
      {
         name=n;
         job=j;
         salary=sal;
       }
      public void display()
      {
        System.out.println(name+"\t"+job+"\t"+salary);
       }



  public boolean equals(Object o)
      {

         Emp p=(Emp)o;
          return this.name.equals(p.name)&&this.job.equals(p.job) &&this.salary==p.salary;
       }
  /* public int hashCode()
       {
          return name.hashCode()+job.hashCode()+salary;
       }
     */

      /* public int compareTo(Object o)
       {
          Emp e=(Emp)o;
          return this.name.compareTo(e.name);
           //return this.job.compareTo(e.job);
        //   return this.salary-e.salary;

        }*/
} 

另一個是......

import java.util.*;
class EmpHsDemo
{
      public static void main(String arg[])
      {
          HashSet set=new HashSet();
          set.add(new Emp("Ram","Trainer",34000));
          set.add(new Emp("Ram","Trainer",34000));
          set.add(new Emp("Ravi","Administrator",44000));
          set.add(new Emp("Sachin","Programmer",24000));
          set.add(new Emp("Priyanka","Manager",54000));
          set.add(new Emp("Anupam","Programmer",34000));
          set.add(new Emp("Sachin","Team Leader",54000));
          System.out.println("There are "+set.size()+" elements in the set.");
          System.out.println("Content of set are : ");
          Iterator itr=set.iterator();
          while(itr.hasNext())
          {
            Emp e=(Emp)itr.next();
            System.out.print(e.hashCode()+"\t");   
            e.display();
          }   


          System.out.println("**********************************");
        Emp e1=new Emp("Ravi","Administrator",44000);
        System.out.println("Removing following Emp from the set...");
        System.out.print(e1.hashCode()+"\t");
        e1.display();
        set.remove(e1);
        System.out.println("No. of elements after removal "+set.size());
       /* Emp e2=new Emp("Anupam","Programmer",34000);
        System.out.println("Searching following Emp in the set...");
        System.out.print(e2.hashCode()+"\t");
        e2.display();
        System.out.println("Results of searching is : "+set.contains(e2));*/
      }
}

現在我做了一項研究

  1. 如果我注釋hashcode()方法而不注釋equals()方法,它將使用它允許副本,因為Ram顯示兩次以及內存地址我得到以下結果..
There are 7 elements in the set.
Content of set are : 
374283533   Priyanka    Manager 54000
1660364311  Ram Trainer 34000
1340465859  Ravi    Administrator   44000
2106235183  Sachin  Programmer  24000
2031692173  Ram Trainer 34000
603737068   Anupam  Programmer  34000
148669801   Sachin  Team Leader 54000
**********************************
Removing following Emp from the set...
1807500377  Ravi    Administrator   44000
No. of elements after removal 7

2。 如果我取消注釋hashcode()方法和equals()方法,我得到這個結果

There are 6 elements in the set.
Content of set are : 
1546622676  Sachin  Team Leader 54000
-302767206  Anupam  Programmer  34000
149315535   Ravi    Administrator   44000
199998062   Sachin  Programmer  24000
1407883922  Priyanka    Manager 54000
597555555   Ram Trainer 34000
**********************************
Removing following Emp from the set...
149315535   Ravi    Administrator   44000
No. of elements after removal 5

3。 如果我只注釋equals()方法而不是hashcode(),那么我得到以下結果

There are 7 elements in the set.
Content of set are : 
1546622676  Sachin  Team Leader 54000
-302767206  Anupam  Programmer  34000
149315535   Ravi    Administrator   44000
199998062   Sachin  Programmer  24000
1407883922  Priyanka    Manager 54000
597555555   Ram Trainer 34000
597555555   Ram Trainer 34000
**********************************
Removing following Emp from the set...
149315535   Ravi    Administrator   44000
No. of elements after removal 7

請告知三種方法背后的共鳴......!

不值得閱讀您發布的所有信息。

Joshua Bloch說應該重寫hashCode和equals。 這是你應該怎么做,沒有例外。

HashSet有許多桶。 它使用hashCode()來確定元素屬於哪個存儲桶,然后在該存儲桶內,使用equals()來查找該存儲桶中是否存在該元素。

這些方法的默認實現是hashCode()使用系統身份哈希碼,這可能是它的內存位置,但是獨特之處在於系統將嘗試使用所有“合理實際”嘗試使兩個對象沒有相同的系統identity hashcode和equals比較兩個對象的內存位置。 (請注意,系統標識哈希碼不能保證產生唯一的哈希值;相反,它會嘗試真正地,非常非常難以為您提供獨特的哈希值。請參閱Java Bug 6321873以進一步閱讀此事。)

因此,掌握了這些知識,可以通過各種方法的邏輯應用來預測不同的方法,無論它們是實現還是使用默認實現。

在你的第一種情況下,Ram出現在兩個不同的桶中,因此兩個Ram對象永遠不會相互比較。 它們使用以下行進行比較(至少在Sun實現中)

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

這是迭代桶中的每個對象。 它們的哈希值不相等,所以它永遠不會檢查確定對象本身是否等於所提供的對象。

在你的第二個案例中,它可以按照你的預期運作,並指出一個有兩個不同職位和薪水的人將被視為不同的人。

在你的第三種情況下,Ram兩次進入同一個桶。 但是因為使用了默認的equals方法,並且這兩個對象是不同的對象,所以它會再次添加。

同樣值得重申的是,duffymo的回答完全忽略了你的問題; 在99.9%的情況下,我會說這是錯誤的,我們應該先了解你的問題范圍。 這是極少數情況下忽略您的問題的正確電話之一 永遠不應該只覆蓋hashcode和equals中的一個。 你應該總是不做或兩者兼而有之,不要只做一件。

1.2個對象相等時,它們應該具有same hashcode

2.如果2個對象具有same hascode,則它們必須相互調用equals()以查看它們是否相等。

3.如果hashcode匹配不必要,它們都是相等的。

4.因此,它非常重要 ,當equals()方法被覆蓋以后, hashcode() 的方法也必須重寫。

5. HashSet取入的檢查,其中此對象在適合的對象時HashSet ,然后是有具有相同散列碼的任何對象如果有則兩個都考慮到水桶same hashcode作為標簽 ,然后調用equals()彼此看,如果他們真的是平等的。

HashSet使用HashMap作為數據的內部表示。 HashSet.add()HashSet.remove()處理hash值(你在hashCode()方法中提供。一旦你注釋hashCode() ,所有的賭注都會被關閉。

在這個問題上,我的心在某種程度上依賴於duffymo,但另一方面,我幾乎和做某事一樣惡毒,因為你的權威告訴了你,沒有理解。

corsiKa已正確回答。 只需添加幾點即可簡化操作。 @ user1582269你正在使用Set Algo和Hashing是使用過的數據結構。 根據Set概念 - Set中的每個元素都應該是唯一的。 不允許復制元素。 哪個基礎元素將是唯一的? 為了實現這種唯一性,應該重寫equals()方法。 即Emp 1應該與Emp 2不同。現在您正在使用哈希數據結構。 散列可確保元素的存儲,檢索和搜索方式。 為了使Hashing有效地工作Hash函數,即hashCode()應該被覆蓋,這樣就不會有任何沖突。

應閱讀corsiKa的解釋,以獲得有關散列的更多解釋。 因此,如果你不覆蓋hashCode(),默認的hashCode()實現將返回一些桶id(假設數組中的某個索引)說例如4.所以如果empX元素已經存儲在桶ID 4,並且另一個員工empY相同hashCode即返回4然后empX和empY之間會發生沖突。

希望這能澄清你的懷疑。

暫無
暫無

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

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