Hashcode()Vs Equals()

use*_*269 3 java collections hashset

我有两个以下的课程..

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;

        }*/
} 
Run Code Online (Sandbox Code Playgroud)

另一个是......

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));*/
      }
}
Run Code Online (Sandbox Code Playgroud)

现在我做了一项研究

  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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

请告知三种方法背后的共鸣......!

duf*_*ymo 7

不值得阅读您发布的所有信息.

Joshua Bloch说应该重写hashCode和equals. 这是你应该怎么做,没有例外.

  • 是的,不是.一方面,是的 - 这是Java中的绝对*事物之一.另一方面强烈而响亮的没有 - 你应该*总是*尝试在应用之前理解某些东西是如何工作的,而不仅仅是基于权威声明. (3认同)

cor*_*iKa 5

HashSet具有多个存储桶。它使用hashCode()来确定元素所属的存储桶,然后在该存储桶equals()中查找该存储桶中是否存在元素。

这些方法的默认实现是hashCode()使用系统标识哈希码,这可能是它的内存位置,但是唯一之处在于,系统将使用所有“合理可行”的尝试进行尝试,以确保没有两个对象具有相同的系统标识哈希码,和equals比较两个对象的内存位置。(请注意,不能保证系统标识哈希码会产生唯一的哈希值;相反,它确实非常努力地尝试为您提供唯一的哈希值。有关此问题的进一步阅读,请参阅Java错误6321873。

因此,有了这些知识,就可以通过对各种方法进行逻辑应用来预测不同的方法,无论这些方法是实现还是使用默认实现。

在第一种情况下,Ram出现在两个不同的存储桶中,因此这两个Ram对象永远不会相互比较。使用以下行比较它们(至少在Sun实现中)

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
Run Code Online (Sandbox Code Playgroud)

这遍历了存储桶中的每个对象。它们的哈希值不相等,因此将永远无法检查确定对象本身是否等于所提供的对象。

在第二种情况下,它会按您预期的那样工作,请注意具有两个不同职位和薪水的人将被视为不同的人。

在第三种情况下,Ram两次进入相同的存储桶。但是,由于使用了默认的equals方法,并且两个对象是不同的对象,因此将其第二次添加。

同样值得重申的是,达菲的答案完全忽略了您的问题。在99.9%的情况下,我会说这是错误的事情,我们应该首先了解您的问题范围。这是忽略您的问题的正确选择的极少数情况之一。您永远不应仅覆盖哈希码和等于之一。您应该始终不做任何一件事情,或者两者都不做,永远不要只做一件。