HashSet does not realize that two objects are the same

Kaylo :

I have looked at the other times this question has been asked on StackOverflow, but none of the other use cases seem to solve my problem. HashSet does not seem to realize that two objects are the same.

Basically, this is my class.

private static class Inconsistency
    {
        int a;
        int b;
        boolean isConsistency;


        //Default constructor. To be used when we don't have an inconsistency
        public Inconsistency()
        {
            this.a = -1;
            this.b = -1;
            this.isConsistency = false;
        }

        public Inconsistency(int a, int b, boolean isConsistency)
        {
            this.a = a;
            this.b = b;
            this.isConsistency = isConsistency;
        }

        @Override
        public String toString()
        {
            if (this.isConsistency) 
            {
                return "(" + this.a + ", " + this.b + ")";
            } 
            else 
            {
                return "No inconsistency";
            }

        }
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + a;
            result = prime * result + b;
            result = prime * result + (isConsistency ? 1231 : 1237);
            return result;
        }

        @Override
        public boolean equals(Object other)
        {

            if (this == other)
            {
                return true;
            }
            if (other == null)
            {
                return false;
            }

            if (this.getClass() != other.getClass()) 
            { 
                return false; 
            }

            Inconsistency otherInconsistency = (Inconsistency) other;
            return ((this.a == otherInconsistency.a) && (this.b == otherInconsistency.b) && (this.isConsistency == otherInconsistency.isConsistency))
                || ((this.a == otherInconsistency.b) && (this.b == otherInconsistency.a) && (this.isConsistency == otherInconsistency.isConsistency));
        }
    }

I'm trying to store objects of my class inside a hashmap.

With the way I'm defining my equals method, an Inconsistency A (10, 20, true), should be equal to another Inconsistency B (20, 10, true) and when I test my equals method, this works correctly. However, when I try to insert both A and B into a HashSet, they both erroneously get added. I understand that I should manipulate my hashcode function but I'm not sure how to go about it.

Here's a driver showcasing the erroneous behaviour

    Inconsistency A = new Inconsistency(10,20, true);
    Inconsistency B = new Inconsistency(20,10, true);

    System.out.println(A.equals(B)); // prints true as expected


    HashSet<Inconsistency> test = new HashSet<>();
    test.add(A);
    test.add(B);

    System.out.println(test); // prints [(10, 20), (20, 10)]. The two objects are equal but are both added to hashset

Just so the question is clear, How do I go about making sure that the two equal objects A and B both won't be added to my HashSet?

Louis Wasserman :

Your definition of equals means that two Inconsistency objects with their elements reversed are .equals, but your definition of hashCode does not return the same hash code if a and b are in a different order, which is a requirement if a HashSet or other hash-based collection is to work properly.

The simplest approach to fixing this is to do something commutative -- something that has the same result whichever order a and b are in. For example:

result = prime * result + a + b;

instead of

result = prime * result + a;
result = prime * result + b;

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=329565&siteId=1