Basic java equals() override help needed - java

I am currently working on a simple line program in java. There will be no actual GUI, so it is completely text based.
We are required to have a point class and a line class that includes to point objects.
The problem I encountered was involving the equals method for my point class. Considering each point only has two POSITIVE int values, an x and a y, and I'm having issues here, I'm worried I will have problems when I have to compare lines, which will involve comparing the points, the int width and the string color.
This is what the code for my equals method for my point class looks.
#Override
public boolean equals(Point that) {
if(this==that)
return true;
//if
if(this.x==that.getX() && this.y==that.getY())
return true;
return false;
}
Any and all help would be appreciated.

The signature needs to contain Object, not Point. You then need the obvious checks to make sure the object is in fact a point and it's non-null.
Apart from that, as you've put it there I don't see any problem with the method, it's reflexive, symmetric, consistent and transitive as far as I can make out. If your class used doubles then I'd say put a delta value in when comparing them - but obviously with ints that's not a problem.
The indirect problem though is that you really should override hashcode as well to behave in the same way, otherwise you could run into strange issues when adding your points to collections that make use of hashcode() (by contract they're expected to compare the objects in the same way.)

For a simple class, containing only two integers, the following hashCode and equals methods are appropriate:
/*
* (non-Javadoc)
*
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}

You showed the Line class equals method but I don't think a Line can equals to a Point. Line can contain a Point. did you mean Point equals method?

Your question seems to be about performance and the Object.equals() method. You should read this:
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode%28%29
Your class should override the hashCode() method.

Look at the definition of the Object.equals() method. In particular look at the type of the parameter. Any override of equals() must have an Object parameter.
public boolean equals(Object that) { ... }

Let me try this:
#Override
public boolean equals(Object o)
{
//Cast the object o to Point instance
if(!(o instanceof Point))
return false;
Point obj = (Point)o;
if(obj==null)
return false;//Checking if null
else if.....//test properties using cast object obj
}

Related

hashCode() and equals() with Class<T>

I've bumped into an unexpected problem with equals() and hashcode().
Eclipse refused to generate them properly, because Class does not override them. Oh uh.
So I had to compare them by .getName() result, but it is ugly.
private Class<T> clientClass;
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + clientClass.getName().hashCode();
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof MessageChannel)) return false;
MessageChannel<?, ?> other = (MessageChannel<?, ?>) obj;
if (!clientClass.getName().equals(other.clientClass.getName())) return false;
return true;
}
Note that T is a parameter.
How to do this correctly?
You do not need to do something special to deal equals and hashcode for Class. The current behaviour (inherited from Object) is semantically correct. (If Eclipse is warning you otherwise, ignore it. The warnings are incorrect.)
Isn't it possible that I get two different instances of Class representing the same class? Object just uses == on them afaik. Perhaps with two classloaders or whatever, I'm not that familiar with this reflection magic.
Yes it is possible.
But in that case, they are in fact different classes from the perspective of the Java type system. (See JLS 4.3.4 for details.) And hence, you should be treating them as not equal.
I would suggest that you do following
#Override
public boolean equals(Object that) {
return EqualsBuilder.reflectionEquals(that, this);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
You can read more about this nice builder on
http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/package-summary.html

Java: Comparing a class with another within that class using a my own .equals

I am making a method .equals replacing the equals method used. It accepts a object. I want it to check if that object equals the class that runs the .equals class.
I know I want to compare all the private methods I have to that object.
Is there a way to do this without making another private class to get the private variables from the object? How do I do this to compare equality not identity? I am stuck on this. Do i have to use == to compare?
Also looking online i see others use recursion. If this is the way i have to do it can you show and explain it to me?
so an example i have
public boolean equals(Object o)
{
this is in a class we will call bobtheBuilder (first thing to pop in my head)
I want to check if the object o is equal to the class.
bobTheBuilder has private object array and a private int. I assume I want to check if the array and int of this class equal the array and int of the object. First I know i need to check if it equals null so
private _arrayObject[];
private _integerBob;
public boolean equals(Object o)
{
boolean result = true;
if (o == null)
result = false
bobTheBuilder compared = (bobTheBuilder) o;
if(compared.getArray != _arrayObject[] || compared.getInt != _integerBob)
result == false
return result
}
I know that equal checks for equality not identity so I assume this is wrong. How would I do this
Adapted from the examples in Effective Java, 2nd edition by Joshua Bloch:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof BobTheBuilder)) {
return false:
}
BobTheBuilder bob = (BobTheBuilder) o; //guaranteed to succeed
return Arrays.equals(bob._arrayObject, _arrayObject)
&& bob._integerBob == _integerBob;
}
Don't forget to override hashCode as well.
The text in the book refers to the contract set out for the equals method in Object which is here
So, you have a private array X and an int Y in a class Z.
Now, for checking the equality and not indentity,
First thing you should have setters and getters that will set and return the value of the private variables, e.g.
public void setArrayX(Object[] arr), public Object[] getArrayX()
2.now, the eqauls method would look like,
boolean equals(Object o) {
if(Arrays.equals(this.getArrayX(),o.getArrayX()) && this.getIntY() == o.getIntY())
return true;
return false;
}
I think the best way to check the class is through the
someObject.getClass().isInstance(anotherObject)
command.
This works with inheritance as well.

How to properly implement equals in Java

I need to implement the equals method in some class A. Class A has an orderer collection of Enum type, and the behaviour I want to achive is that equals returns true for two instances of Class A that have exactly the same Enum values in the collection (in exactly the same positions of the collection).
As I'm new to java, I'm having problems with this, and I dont know how to properly implement equals or the hashcode methods, so any help would be good :)
If you're using eclipse (netbeans has similar features, as do most java IDEs), you can simply got to the "Source" menu, and choose "Generate hashcode() and equals()". Then you select the fields you want to be considered (in your case the list of enum values.
That being said, assuming you already have the enum, here's the code that eclipse generated for me. Not that hashcode usually involves a prime number, as well as multiplication and addition. This tends to give you somewhat decent distribution of values.
public class Foo {
private List<FooEnum> enumValues;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((enumValues == null) ? 0 : enumValues.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Foo other = (Foo) obj;
if (enumValues == null) {
if (other.enumValues != null)
return false;
}
else if (!enumValues.equals(other.enumValues))
return false;
return true;
}
}
The overridden equals method will look like this
public boolean equals(Object o) {
if ((o instanceof yourtype) &&
(((yourtype)o).getPropertyToTest() == this.propertyToTest)) {
return true;
}
else {
return false;
}
}
The overridden hashCode method will look like this
public int hashCode() { return anIntRepresentingTheHashCode}
Pulling from the javadocs, your equals method must meet the following criteria:
reflexive - x.equals(x) is true
symmetric - if x.equals(y) then y.equals(x)
transitive - if x.equals(y) and y.equals(z) then x.equals(z)
consistent - if x.equals(y) is true, then it's always true unless the object is modified
null - x.equals(null) is false
Also, if two objects are equal based on the equals method, they must have identical hash codes.
The reverse is not true. If two objects are not equal, they may or may not have identical hash codes
Use EnumSet It retains natural order as per java docs also and it is optimized for Enums only.
The iterator returned by the iteratormethod traverses the elements in their natural order (the order in which the enum constants are declared). The returned iterator is weakly consistent: it will never throw ConcurrentModificationException and it may or may not show the effects of any modifications to the set that occur while the iteration is in progress.
You can use EnumSet as below
import java.util.EnumSet;
public enum Direction {
LEFT,
RIGHT,
ABOVE,
BELOW;
private static EnumSet<Direction> someDirection = EnumSet.of(Direction.LEFT,Direction.RIGHT) ;
}
Now because you are using EnumSet equals and Hashcode method will be provided default from AbstractSet which is parent class of EnumSet
So You don't have to care about them.

How to Write an Equality Method in Java

Consider adding an equality method to the following class of simple points:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
// ...
}
// my definition of equals
public boolean equals(Point other) {
return (this.getX() == other.getX() && this.getY() == other.getY());
}
What's wrong with this method? At first glance, it seems to work OK:
Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);
Point q = new Point(2, 3);
System.out.println(p1.equals(p2)); // prints true
System.out.println(p1.equals(q)); // prints false
However, trouble starts once you start putting points into a collection:
import java.util.HashSet;
HashSet<Point> coll = new HashSet<Point>();
coll.add(p1);
System.out.println(coll.contains(p2)); // prints false
How can it be that coll does not contain p2, even though p1 was added to it, and p1 and p2 are equal objects?
While it is true that you should implement hashCode() when you implement equals(), that is not causing your problem.
That is not the equals() method you are looking for. The equals method must always have the following signature: "public boolean equals(Object object)". Here is some code.
public boolean equals(Object object)
{
if (object == null)
{
return false;
}
if (this == object)
{
return true;
}
if (object instanceof Point)
{
Point point = (Point)object;
... now do the comparison.
}
else
{
return false;
}
}
The Apache EqualsBuilder class is useful for equals implementations. The link is an older version, but still applicable.
If you liked the Apache EqualsBuilder, you will probably like the Apache HashCodeBuilder class as well.
Edit: updated the equals method example for standard shortcuts.
You must implement hashCode() whenever you override equals(). These two work together, and they must give consistent results at all times. Failing to do so produces just the erroneous behaviour you observed.
This is explained in more detail e.g. in Effective Java 2nd Edition, Item 9: Always override hashCode when you override equals.
Works well by overriding hashcode !
Always remember : override hashCode when you override equals.
#Override public int hashCode() {
return (41 * (41 + getX()) + getY());
}
This is my implementations of hashCode.
As per contract on equals() you need to implement hashCode() as well.
From the JavaDoc on equals():
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
In addition to the other answers:
If you are using Eclipse as IDE, you can simply use "Source" --> "Generate hashCode() and equals() to get a basic implementation. Do with that what ever you want.
When overriding equals, you also have to override hashCode (in particular, if you are going to use HashSet or HashMap...). A suitable (though not to clever) implementation would be:
int hashCode() {
return x * 31 + y;
}
Another point (no pun intended): You are not actually overriding the equals(Object) method defined in class Object, but instead are defining a new one. The correct way would be:
boolean equals(Object other) {
if (other == this) return true;
else if (!(other instanceof Point)) return false;
else {
Point p = (Point)other;
return x == p.getX() && y == p.getY();
}
}
Note, that the equals method has a pretty strong contract associated with it, which you are to fulfill.

Performance of Equality in Java ( instanceOf vs isAssignableFrom )

this question is specifically about the performance and to some extent brevity of the various implementation alternatives.
I refreshed myself with this article on implementing equality right. My question particularly corresponds to canEqual (to ensure equivalence relation).
instead of overloading canEquals method to use instanceOf in every class in the hierarchy( instance of paramenter is a compile time class ). Why not use isAssignableFrom ( which is resolved dynamically ) in only the top level class. Makes for much concise code and you dont have to overload a third method.
While, this alternative works. Are there any performance considerations that I need to be aware of?
enum Color {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;
}
class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof Point) {
Point that = (Point) other;
//Option 1
//result = (that.canEqual(this) && this.getX() == that.getX() && this.getY() == that.getY());
//Option 2
//result = (that.getClass().isAssignableFrom(this.getClass()) && this.getX() == that.getX() && this.getY() == that.getY());
//Option 3
//result = (getClass() == that.getClass() && this.getX() == that.getX() && this.getY() == that.getY());
}
return result;
}
#Override public int hashCode() {
return (41 * (41 + x) + y);
}
public boolean canEqual(Object other) { return (other instanceof Point); }
}
public class ColoredPoint extends Point{
Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
#Override public boolean equals(Object other) {
boolean result = false;
if (other instanceof ColoredPoint) {
ColoredPoint that = (ColoredPoint) other;
result = (this.color.equals(that.color) && super.equals(that));
}
return result;
}
#Override public int hashCode() {
return (41 * super.hashCode() + color.hashCode());
}
#Override public boolean canEqual(Object other) { return (other instanceof ColoredPoint); }
public static void main(String[] args) {
Object p = new Point(1, 2);
Object cp = new ColoredPoint(1, 2, Color.INDIGO);
Point pAnon = new Point(1, 1) {
#Override public int getY() {
return 2;
}
};
Set<Point> coll = new java.util.HashSet<Point>();
coll.add((Point)p);
System.out.println(coll.contains(p)); // prints true
System.out.println(coll.contains(cp)); // prints false
System.out.println(coll.contains(pAnon)); // prints true
}
}
Update: Actually, your method is not technically valid like I first thought, because it breaks the symmetry contract of equals for subclasses that don't override equals:
Point p = new Point(1, 2);
Point pAnon = new Point(1, 1) {
#Override public int getY() {
return 2;
}
};
System.out.println(p.equals(pAnon)); // prints false
System.out.println(pAnon.equals(p)); // prints true
The reason is that p.getClass().isAssignableFrom(pAnon.getClass()) is true while the inverse, pAnon.getClass().isAssignableFrom(p.getClass()) is false.
If you are not convinced by this, try actually running your code and compare it to the version in the article: you will notice that it prints true, false, false, instead of true, false, true like the example in the article.
unless you want to allow comparing classes of different types, the easiest, safest, most concise and probably most efficient impl is:
(getClass() == that.getClass())
All the answers given so far don't answer the question - but point out the equals() contract. Equality must be an equivalence relation (transitive, symmetric, reflexive) and equal objects must have the same hash code. That extends perfectly fine to subclasses - provided subclasses don't themselves override equals() or hashCode(). So you have two choices - you either inherit equals() from Point (so ColoredPoint instances are equal if they have the same coordinates, even if they have a different color), or you override equals() (and now must make sure a Point and a ColoredPoint are never equal).
If you need to perform a pointwise comparison, then don't use equals() - write a method pointwiseEquals() instead.
Whatever you choose to do, you still have to perform the class check in equals().
getClass() == that.getClass()
is clearly the best performer, but it does break if you expect to be able to equality test subclasses that don't themselves override equals() (and in practice, the only way you can guarantee that is to make the class or the equality methods final and not allow any subclasses to override at all). If it's a choice between instanceOf and isAssignableFrom, there's no practical difference, they both in fact perform the same run-time test (the only difference is, instanceOf can perform a compile-time sanity check, but in this case, it can't know anything when the input is just Object). In both cases, the runtime check is identical - check for the target class in the object's listed interfaces (which doesn't apply here, since we're not checking for an interface), or walk up the class hierarchy until we either find the listed class or get to the root.
See my answer for What is the difference between equality and equivalence?.
You can't equate two objects from different classes because it breaks symmetry.
Edit:
It comes down to whether x in the following:
if (other instanceof Point) {
Point that = (Point) other;
boolean x = that.getClass().isAssignableFrom(this.getClass());
}
has the same power as getClass() == that.getClass().
According to #waxwing's answer it doesn't.
Even if it were correct, I don't see any performance benefit here by calling that.getClass().isAssignableFrom.
Here's my Second Answer to the clarified question
Consider when we call Point.equals(ColoredPoint cp);
Point.equals() first checks for
if (other instanceof Point)...
Which passes. Out of the three options presented, all three of them check that the other object, in this case a ColoredPoint, satisfies some more test. The options are:
will only be true if Point is an instanceof ColoredPoint, which is never
will only be true if ColoredPoint is assignable from Point, which is never
will never be true.
From a performance (and design) perspective, there was no value in checking for other instanceof Point, because the actual behavior OP wants (which he has been unable to express) is that for his particular use case, equality between these Objects means they must be the same class.
Therefore, for both performance and design, just use
this.getClass() == that.getClass()
as was suggested by #jthalborn
When a later coder sees instanceof or isAssignableFrom in your code, he will think that subclasses are allowed to equal the base class, which is completely misleading.
I think you solution will fail because it isn't transitive OOPS, symmetric. See The chapter from Effective Java
Point p = new Point(2,3);
ColoredPoint cp = new ColoredPoint(2,3, Color.WHITE);
I believe (haven't run your code) that
p.equals(cp) is true
but
cp.equals(p) is false
Though I don't fully understand your code - it refers to canEquals() which was commented out. The short answer is that you either have to ignore color for equality, or you have to do what #jthalborn suggested.
OK we here we have the example from Effective Java (i have the 2nd Edition 2008).
The example is in ITEM 8: OBEY THE GENERAL CONTRACT WHEN OVERRIDING EQUALS starting from page 37 (I write this in case you want to check).
class ColoredPoint extends Point{} and there are 2 attepts in demostrating why instanceof is BAD. The first attempt was
// Broken - violates symmetry!
#Override public boolean equals(Object o) {
if (!(o instanceof ColorPoint))
return false;
return super.equals(o) && ((ColorPoint) o).color == color;
}
and the second was
// Broken - violates transitivity!
#Override public boolean equals(Object o) {
if (!(o instanceof Point))
return false;
// If o is a normal Point, do a color-blind comparison
if (!(o instanceof ColorPoint))
return o.equals(this);
// o is a ColorPoint; do a full comparison
return super.equals(o) && ((ColorPoint)o).color == color;
}
First of all the second IF will never be reached. If 'o' is not a Point which is a superclass to ColorPoint how might it happen a non-Point to be a ColorPoint ??????
So the second attempt from the beginning is wrong ! Where the only chance for a TRUE comparison is super.equals(o) && ((ColorPoint)o).color == color;, which is not enough !!
a solution here would be:
if (super.equals(o)) return true;
if (!(o instanceof ColorPoint))
if ((o instanceof Point)) return this.equals(o);
else return false;
return (color ==((ColorPoint)o).color && this.equals(o));
obj.getClass() is used for very specific equals(), But your implementations depends of your scope. How do you define that two objects are equal or not? Implement it and it will work accordingly.

Categories

Resources