Hashcode() Vs Equals()

给你一囗甜甜゛ 提交于 2020-01-13 05:16:13

问题


I have below this two classes ..

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;

        }*/
} 

and the other one is..

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));*/
      }
}

Now I was doing one research that is

  1. If I comment hashcode() method and not comment equals () method that is it will use it allows the duplicate as Ram is shown twice along with memory address I get the following result..
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 . If I uncomment hashcode() method and equals () method , I get this result

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 . If I comment equals() method only and not hashcode() then I get the following result

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

Please advise what the reson behind there three approaches ..!


回答1:


A HashSet has a number of buckets. It uses the hashCode() to determine which bucket an element belongs in, and then within that bucket, it uses equals() to find if the element exists in that bucket or not.

The default implementations of those methods are hashCode() uses a system identity hashcode, which is probably it's memory location, but is unique in that the system will make an attempt using all "reasonably practical" attempts to make no two objects have the same system identity hashcode, and equals compares the memory locations of the two objects. (Note that system identity hashcode is not guaranteed to produce unique hashes; rather it tries really, really, really hard to give you unique hashes. See Java Bug 6321873 for further reading on the matter.)

So armed with this knowledge, the different approaches can be predicted with a logical application of the various methods given whether they are implemented or using the default implementation.

In your first case, Ram shows up in two different buckets, so the two Ram objects never get compared against eachother. They are compared using the following line (in the Sun implementation, at least)

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

This is iterating over every object in the bucket. Their hashes aren't equal, so it will never get to the check of determining if the object itself is equal to the one provided.

In your second case, it works as you might expect, noting that a person with two different positions and salaries will be considered different people.

In your third case, Ram enters the same bucket twice. But because the default equals method is used, and the two objects are different objects, it gets added a second time.

It also also worth re-iterating that duffymo's answer completely ignores your question; in 99.9% of cases I would say that's the wrong thing to do, and that we should understand your problem-scope first. This is one of the very few cases where it's the right call to ignore your question. You should never override only one of hashcode and equals. You should always do neither or both, never just one.




回答2:


It's not worth reading all the info you've posted.

Joshua Bloch says hashCode and equals should be overridden together. Here's how you should do it, no exceptions.




回答3:


1. When 2 objects are equal then they should have same hashcode.

2. If 2 object has same hascode, then they must call equals() on each other to see whether are they equal.

3. If hashcode matches its not necessary that they both are equal.

4. So its very important that when equals() method is overridden then, hashcode() method must also be overridden.

5. HashSet when taking an object in checks where this object fits in the HashSet, then is there any object with the same hashcode, if there then both are taken into a bucket with the same hashcode as the label, then calling equals() on each other to see, if they are really equal.




回答4:


HashSet uses HashMap as internal representation of data. HashSet.add() and HashSet.remove() work on hash value (which you provide in your hashCode() method. As soon as you comment hashCode() out, all bets are off.

My heart somewhat lies with duffymo on this one, but on the other hand I'm almost as viciously against doing something because your authority told you so, without understanding.




回答5:


corsiKa has answered correctly. Just adding few more points to simplify things. @user1582269 you are using Set Algo and Hashing is data structure been used. As per Set concept - each element in Set should be unique. Duplication of element is not allowed. On which basis element will be unique ? To achieve this uniqueness equals() method should be overridden. i.e. Emp 1 should be different from Emp 2. Now you are using Hash Data Structure . Hashing ensures how elements are stored, retrieved, searched. For Hashing to work efficiently Hash function i.e hashCode() should be overridden, so that there will not be any collision.

corsiKa's explanation should be read for more explanation about hashing. So if you don't override hashCode(), default hashCode() implementation will return some bucket id (assume some index in array) say e.g. 4. So if empX element is already stored at bucket id 4, and for another employee empY same hashCode i.e. 4 is returned then there will be collision between empX and empY.

Hope this clarifies your doubt.



来源:https://stackoverflow.com/questions/11850929/hashcode-vs-equals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!