Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is equals() not called while adding to HashSet and hashCode matches?

Tags:

java

When I run this code why only hashCode() is called not equals method while my hashCode() implementation generate same hashCode for both entries to HashSet?

import java.util.HashSet;  public class Test1 {     public static void main(String[] args) {         Student st=new Student(89);         HashSet st1=new HashSet();         st1.add(st);         st1.add(st);         System.out.println("Ho size="+st1.size());     } } class Student{     private int name;     private int ID;     public Student(int iD) {         super();         this.ID = iD;     }     @Override     public int hashCode() {         System.out.println("Hello-hashcode");         return ID;     }     @Override     public boolean equals(Object obj) {         System.out.println("Hello-equals");         if(obj instanceof Student){             if(this.ID==((Student)obj).ID){                 return true;             }             else{                 return false;             }         }         return false;       } } 

The output for this is:

Hello-hashcode Hello-hashcode Ho size=1 
like image 226
san9w Avatar asked Aug 15 '14 18:08

san9w


People also ask

What happens if we do not override hashCode () and equals () in HashSet?

Overriding only equals() method without overriding hashCode() causes the two equal instances to have unequal hash codes, which violates the hashCode contract (mentioned in Javadoc) that clearly says, if two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two ...

Why do we override hashCode and equals method?

In order to use our own class objects as keys in collections like HashMap, Hashtable etc.. , we should override both methods ( hashCode() and equals() ) by having an awareness on internal working of collection. Otherwise, it leads to wrong results which we are not expected.

How hashCode () and equals () methods are used in HashMap?

In HashMap, hashCode() is used to calculate the bucket and therefore calculate the index. equals() method: This method is used to check whether 2 objects are equal or not. This method is provided by the Object class. You can override this in your class to provide your implementation.


1 Answers

The hash set checks reference equality first, and if that passes, it skips the .equals call. This is an optimization and works because the contract of equals specifies that if a == b then a.equals(b).

I attached the source code below, with this check highlighted.

If you instead add two equal elements that are not the same reference, you get the effect you were expecting:

    HashSet st1=new HashSet();     st1.add(new Student(89));     st1.add(new Student(89));     System.out.println("Ho size="+st1.size()); 

results in

$ java Test1 Hello-hashcode Hello-hashcode Hello-equals Ho size=1 

Here's the source code from OpenJDK 7, with equality optimization indicated (from HashMap, the underlying implementation of HashSet):

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; //                                         v-- HERE         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; } 
like image 123
that other guy Avatar answered Oct 04 '22 16:10

that other guy