utkarsh shukla
utkarsh shukla

Reputation: 15

Is there any internal mapping of an object's hashcode to what we override in our classes

Sets care about uniqueness, so while implementing set in our program we must override the java.lang.Object equals() and hashCode() method, so that we do not end up with duplicates. A reference holds its validity within the context of the single and current instance of the JVM, keeping this in mind I tried to code my program this way. Within TestSet.main (lines 4-6). I have tried to put my query in a practical way by using comments in those lines.

class TestCase  {
    transient private int x;
    private int y;
    public TestCase(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public boolean equals(Object o) {
        if (o instanceof TestCase && (((TestCase) o).getXValue() == getYValue()))
            return true;
        else
            return false;
    }
    public int hashCode() {
        return x + y;
    }
    public int getXValue() {
        return x;
    }
    public int getYValue() {
        return y;
    }
}

class TestSet {
    public static void main(String[] args) {
        TestCase tc1 = new TestCase(4, 8);
        TestCase tc2 = new TestCase(4, 8);
        Set<TestCase> set = new HashSet<TestCase>();
        set.add(tc1);//succeeds
        set.add(tc2);//succeeds
        System.out.println(set.add(tc2));//fails and gives us false.
        tc2 = new TestCase(4, 8);
        System.out.println(set.add(tc2));//succeeds and gives us true?
        System.out.println(set.size());
        System.out.println(set.contains(tc1));
        System.out.println(set.contains(tc2));
    }
}

Upvotes: 1

Views: 59

Answers (3)

gevorg
gevorg

Reputation: 5065

First you better fix or remove your equals method completely. Your situation has nothing to do with how hashCode method is working, I will explain how it works below:

// Set is looking for tc2 and finds object with same ref, because of previous set.add(tc2);
System.out.println(set.add(tc2));//fails and gives us false.

// You create new object with new reference.
tc2 = new TestCase(4, 8);

// Yes, because you changed tc2 variable and assigned new reference to it.
System.out.println(set.add(tc2));//succeeds and gives us true?

Upvotes: 0

Louis Wasserman
Louis Wasserman

Reputation: 198581

You have a typo in your equals method: you are comparing one element's x to the other's y. This makes pretty much no sense; you should be comparing both x's and both y's.

You should implement equals as

return o instanceof TestCase
   && ((TestCase) o).getXValue() == getXValue()
   && ((TestCase) o).getYValue() == getYValue();

The reason the second .add(tc2) returns false is because HashSet's implementation uses a == check as an optimization, and that happens to catch that particular case. That doesn't change the brokenness of your .equals method.

Upvotes: 2

Jesper
Jesper

Reputation: 207026

The rule that equals and hashCode must conform to is: if two objects are equal, then their hash codes must be the same.

Note that this does not mean the opposite: if two objects have the same hash code, it does not necessarily mean that the objects are equal.

Your code violates this rule, so you get unpredictable results when you put those two objects in a HashSet.

Upvotes: 0

Related Questions