I believe this question applies equally well to C# as to Java, because both require that {c,C}ompareTo be consistent with {e,E}quals:
Suppose I want my equals() method to be the same as a reference check, i.e.:
public bool equals(Object o) {
return this == o;
}
In that case, how do I implement compareTo(Object o) (or its generic equivalent)? Part of it is easy, but I’m not sure about the other part:
public int compareTo(Object o) {
MyClass other = (MyClass)o;
if (this == other) {
return 0;
} else {
int c = foo.CompareTo(other.foo)
if (c == 0) {
// what here?
} else {
return c;
}
}
}
I can’t just blindly return 1 or -1, because the solution should adhere to the normal requirements of compareTo. I can check all the instance fields, but if they are all equal, I’d still like compareTo to return a value other than 0. It should be true that a.compareTo(b) == -(b.compareTo(a)), and the ordering should stay consistent as long as the objects’ state doesn’t change.
I don’t care about ordering across invocations of the virtual machine, however. This makes me think that I could use something like memory address, if I could get at it. Then again, maybe that won’t work, because the Garbage Collector could decide to move my objects around.
hashCode is another idea, but I’d like something that will be always unique, not just mostly unique.
Any ideas?
First of all, if you are using Java 5 or above, you should implement
Comparable<MyClass>rather than the plain oldComparable, therefore yourcompareTomethod should take parameters of typeMyClass, notObject:As of your question, Josh Bloch in Effective Java (Chapter 3, Item 12) says:
This means that if c == 0 in the above code, you must return 0.
That in turn means that you can have objects A and B, which are not equal, but their comparison returns 0. What does Mr. Bloch have to say about this?
And
Update: So IMHO with your current class, you can not make
compareToconsistent withequals. If you really need to have this, the only way I see would be to introduce a new member, which would give a strict natural ordering to your class. Then in case all the meaningful fields of the two objects compare to 0, you could still decide the order of the two based on their special order values.This extra member may be an instance counter, or a creation timestamp. Or, you could try using a UUID.