Aks 1316
Aks 1316

Reputation: 382

How HashSet of collection framework identifies duplicate objects? How Hashcode and equals work with custom objects?

I was looking at some code and found one program where they have extended HashSet class of collection. They have created custom employee objects and inserted into Set without implementing Comparable or Comparator. They implemented logic to identify duplicate employee object so if object is already there They can perform update operation if object is not present they can do insert operation. I was trying to understand how set will identify duplicate object without implementiong Comparable or Comparator interface.

I have tried same and also tried to override Hashcode and equals method to understand how Set comparing objects. One thing I have found that while I am adding same object to set its generating same Hashcode. But its not calling equals method I have overrided.

class Employee {
    int id;
    String name;

    Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        System.out.println("HashCode : " + super.hashCode());
    return super.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("Equals : " + super.equals(o));
    return super.equals(o);
    }
}

class LimitedHashSet extends HashSet<Employee> {
    public boolean add(Employee e) {
        if(!super.add(e)){
            return false;
        }
    return true;
    }
}
public class ExtendingHashSet {

    public static void main (String[] args) {
    Employee e0 = new Employee(1,"A");
    Employee e1 = new Employee(2,"B");

    LimitedHashSet obj = new LimitedHashSet();

    System.out.println("Element added ? " + obj.add(e0) + "\n");
    System.out.println("Element added ? " + obj.add(e1) + "\n");
    System.out.println("Element added ? " + obj.add(e0) + "\n");
}
}

Hashcode is use to calculate bucket and equals method identifies its equals or not. So how its working here. Please check output below.

Output:

HashCode : 914424520 Element added ? true

HashCode : 110718392 Element added ? true

HashCode : 914424520 Element added ? false

Upvotes: 4

Views: 324

Answers (1)

Louis Wasserman
Louis Wasserman

Reputation: 198341

Fundamentally, there is no magic.

HashSet and all JDK hash-based collections blindly use the implementations of hashCode and equals definitions for your objects to determine if objects are the same or not. They just call the hashCode and equals methods, and however those work, that's what the hash collections use.

Part of the point of the use of the hashCode method -- part of the point of hash-based data structures in the first place -- is to make it unlikely that the hash-based collection even has to bother calling the equals method to check if two objects are the same. If the hashes aren't the same, then the objects are definitely not equal. So it would call the equals method you have overridden if it needed to, but in your code, it doesn't need to bother calling equals. Furthermore, it also checks reference equality before calling the equals methods, because if two objects are == then they are definitely .equals to each other.

Currently, you are adding e0 twice. By reference equality, e0 == e0, so it doesn't bother calling .equals -- it just finds the matching entry, checks that they're reference-equal, and keeps the existing entry without adding a new element. This is the correct behavior, by the way, since e0 is a duplicate of itself.

Upvotes: 4

Related Questions