Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is "sameness" defined for Java objects?

Tags:

java

equality

I want to add objects of a custom type to a Set. I have several which are the same, i.e. they have the same values for their public variables.

I don't want more than one instance of a "same" object to be added to the set, but each time a new object is created it is always added.

This is because the equals method for class Object implements the most discriminating possible equivalence relation on objects: "For any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true)."

Can I override the equals method for this object to define it differently?

Thanks everyone the problem is solved

Sameness for java objects is defined by overriding the Java Object's equals() method.

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((uri == null) ? 0 : uri.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!(obj instanceof Resource))
        return false;
    Resource other = (Resource) obj;
    if (uri == null) {
        if (other.uri != null)
            return false;
    } else if (!uri.equals(other.uri))
        return false;
    return true;
}
like image 649
Ankur Avatar asked Dec 17 '22 16:12

Ankur


2 Answers

You need to override the equals() and hashCode() methods to tell the HashSet what you consider equal.

If you're using a TreeSet, you should implement Comparable instead.

like image 137
SLaks Avatar answered Dec 29 '22 11:12

SLaks


You should override the equals, and hashCode methods for your custom type.

Be careful though, you can get into all sorts of shit here: for instance if you have sub-types for your custom type, you can run into other equality problems:

class Point {
    final int x;
    final int y;

    public Point(int x, int y) {
        this.x= x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;   //If objects equal, is OK
        if (o instanceof Point) {
           Point that = (Point)o;
           return (x == that.x)  && y == that.y);
        }
        return false;
    }
}

class ColoredPoint extends Point {
   final Color color;
   ColoredPoint(int x, int y, Color color) {
      super(x, y);
      this.color = color
   }
}

Point p1 = new Point(1, 2);
ColoredPoint cp1 = new ColoredPoint(1, 2, Color.BLUE);
ColoredPoint cp1 = new ColoredPoint(1, 2, Color.RED);

As it stands, p1, cp1, and cp2 are all equal. However, obviously cp1 and cp2 are not equal. You'll need to implement an equals in ColoredPoint too, to compare ColoredPoint Objects (but this breaks equality between p1 and cp1, or cp2).

Also, make sure your equals has the signature above. It's a common mistake to define it as public equals(Point that)..., which is wrong.

See http://www.artima.com/lejava/articles/equality.html for a full explanation of the rules for equals and hashCode

like image 38
GKelly Avatar answered Dec 29 '22 11:12

GKelly