views:

246

answers:

6

I have the following situation: I need to sort trees based by height, so I made the Tree's comparable using the height attribute. However, I was also told to overwrite the equals and hashCode methods to avoid unpredictable behaviour.

Still, sometimes I may want to compare the references of the roots or something along those lines using ==. Is that still possible or does the == comparison call the equals method?

+1  A: 

Yes, == will not call hashCode or equals. You can still test for reference equality like this.

Yann Ramin
A: 

== does not call equals. So it's still find for identity checks.

As many implementations of equals start with this == other check you would get a literal StackOverflow if it were calling equals behind the scenes.

Alexander Pogrebnyak
A: 

== tests referential equality. It will not call equals.

Brian
+4  A: 

equals() is meant to compare an object with rules set by the programmer. In your example you compare your trees by height, so you'll write equals() so it compares heights.

==, as you said, compares references. These aren't touched neither by equals() nor by hashCode(). So you won't change its behaviour.

klez
+1  A: 

Overriding the equals() method will have NO effect on the == operator. == is used to test if 2 references point to the same object. equals() method "meaningfully" compares 2 objects.

It is important to realize the implication of the work "meaningful" here. Equality is easier to understand when you are comparing, for instance, 2 Strings or 2 integers. This is why, the equals() method - inherited from the Object class - is already overridden by the String and Wrapper classes (Integer, Float, etc). However, what if you are comparing 2 objects of type Song. Here, equality can be established on the basis of
1) Artist name
2) Song name
3) or some other criterion

Therefore, you have to override the equals() method to "explicitly" determine "when" 2 Song objects are considered equal.

The "unpredictable behavior" you mentioned in your question relates to objects like the one above (Song) behave when dealing with Collections like Map. You SHOULD NOT use these objects in a map until you override both the equals() and hashcode() method. The reason being how hashmap search and indexing works. Refer the JavaDoc for the specifc rules. What you should remember is:
If 2 objects are meaningfully equal, their hashcode should return the same value. However, it is not necessary for 2 objects to be equal, if they return the same hashcode. Again, Java doesn't enforce any rules regarding this. It is your responsibility to implement the equals() and hashcode() methods correctly.

Epitaph
+1  A: 

I think that a bigger question here is whether it is appropriate to implement comparable on these objects. It may be more appropriate to use a Comparator for the operations that work on height, and not embed ordinal computation in the class itself.

My general philosophy on this is to only implement Comparable if there is a truly natural ordering for the object. In the case of a tree node, is height the only way that anyone could ever want to sort? Maybe this is a private class, and the answer is 'yes'. But even then, creating a Comparator isn't that much extra work, and it leaves things flexible in case you decide you want to make that tree node a protected or public class some day.

Kevin Day