Hashcode and Equals for Hashset

106,499

Solution 1

  1. There's no need to call equals if hashCode differs.
  2. There's no need to call hashCode if (obj1 == obj2).
  3. There's no need for hashCode and/or equals just to iterate - you're not comparing objects
  4. When needed to distinguish in between objects.

Solution 2

I think your questions will all be answered if you understand how Sets, and in particular HashSets work. A set is a collection of unique objects, with Java defining uniqueness in that it doesn't equal anything else (equals returns false).

The HashSet takes advantage of hashcodes to speed things up. It assumes that two objects that equal eachother will have the same hash code. However it does not assume that two objects with the same hash code mean they are equal. This is why when it detects a colliding hash code, it only compares with other objects (in your case one) in the set with the same hash code.

Solution 3

according jdk source code from javasourcecode.org, HashSet use HashMap as its inside implementation, the code about put method of HashSet is below :

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

The rule is firstly check the hash, then check the reference and then call equals method of the object will be putted in.

Solution 4

You should read up on how to ensure that you've implemented equals and hashCode properly. This is a good starting point: What issues should be considered when overriding equals and hashCode in Java?

Solution 5

Because in 2nd case you adding same reference twice and HashSet have check against this in HashMap.put() on which HashSet is based:

        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }

As you can see, equals will be called only if hash of key being added equals to the key already present in set and references of these two are different.

Share:
106,499

Related videos on Youtube

Lolly
Author by

Lolly

Updated on March 10, 2020

Comments

  • Lolly
    Lolly about 4 years

    Please clarify my doubt in Hashset. Consider the following code,

    class Person
    {
        String name;
    
        Person(String n)
        {
            name=n; 
        }
        public String getName()
        {
            return name;   
        }
    
        @Override
        public boolean equals(Object arg0) {
    
            System.out.println("in equals");
    
            Person obj=(Person)arg0;
    
            System.out.println("1st "+getName());
            System.out.println("2nd "+obj.getName());
    
            if(this.getName().equals(obj.getName()))
            {
                    return true;
            }
            return false;
        }
    
    
        @Override
        public int hashCode() {
    
            System.out.println("in hash code");
            System.out.println(" value is "+Integer.valueOf(name.charAt(0)));
            return Integer.valueOf(name.charAt(0));
        }
    }
    

    in main I have the following code

    Person obj1=new Person("bcd");
    
    Person obj2=new Person("cde");
    
    Person obj3=new Person("abc");
    
    Person obj4=new Person("abc");
    

    Now if I add these objects to hashset

    Set<Person> sset=new HashSet<Person>();
    
    sset.add(obj1);
    sset.add(obj4);
    sset.add(obj2);
    sset.add(obj3);
    

    I am getting this output

    in hash code                                                                      
    value is 98    
    in hash code   
    value is 97    
    in hash code    
    value is 99    
    in hash code    
    value is 97  
    in equals  
    1st abc     
    2nd abc
    

    Question 1 : why equals() function is called only once for checking obj3 and obj4 ? Why its not checked for rest of the objects ?

    Question 2 : If the answer is because they both have same hash code,only then equals will be called, then why its not called for below code

    sset.add(obj1);
    sset.add(obj4);
    sset.add(obj2);
    sset.add(obj4);
    

    output is :

    in hash code  
    value is 98  
    in hash code   
    value is 97   
    in hash code   
    value is 99   
    in hash code  
    value is 97 
    

    It's not going inside equals() method even though two same objects are added to hash set which has same hash code.

    Question 3 :I iterated the above value and printed the contents but neither hashcode nor equals were called. when its really useful to override hashcode and equals method ?

    Question 4 : When will hashCode() and equals() be called?

    • Daniel
      Daniel about 13 years
      Mmh... do I read this question without code formatting?... Do I format it mayself to understand it?... no, its late, I go home. N8.
    • Erik
      Erik about 13 years
      @Paŭlo Ebermann: Please don't change the meaning of an answer when you edit - it was worded using "hashCode" and not "equals" in 2. intentionally. You're free to write a new answer if you disagree with mine.
    • Paŭlo Ebermann
      Paŭlo Ebermann about 13 years
      @Erik: Sorry, since the question was about calling .equals, I thought the answer should be about this too. (Yes, you are right, I should have added a comment instead.)
  • David Harkness
    David Harkness over 12 years
    HashMap actually calculates the hash to find the correct bucket and uses it before comparing object identity with == or calling equals(), but otherwise this is correct. equals() isn't called in the second example because == already detected the duplicate.
  • Pramod Kumar
    Pramod Kumar almost 12 years
    There's no need for hashCode and/or equals just to iterate - you're not comparing objects --- Then how would it get the current bucket if it don't call hashcode in iteration?