Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hashcode and Equals for Hashset [duplicate]

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?

like image 560
Lolly Avatar asked Mar 22 '11 19:03

Lolly


People also ask

How do I allow duplicates in HashSet?

HashSet doesn't allow duplicates. If you try to add a duplicate element in HashSet, the old value would be overwritten. HashSet allows null values however if you insert more than one nulls it would still return only one null value. HashSet is non-synchronized.

How HashSet detect duplicates?

If the hashcode of two objects are equal then hashset uses equal() to see if the hashcode matched objects are really equal. And if they are equal the hashset knows that the new object is duplicate of something exist in the HashSet. And the add does not happen. The add() of hashcode returns false.

Can HashSet have duplicate objects?

HashSet cannot contain duplicate values. HashSet allows null value. HashSet is an unordered collection. It does not maintain the order in which the elements are inserted.


3 Answers

  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.
like image 123
Erik Avatar answered Sep 28 '22 07:09

Erik


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.

like image 19
Aaron Silverman Avatar answered Sep 28 '22 07:09

Aaron Silverman


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.

like image 12
Sion.Cheng Avatar answered Oct 02 '22 07:10

Sion.Cheng