views:

76

answers:

4

The Java documentation for Comparable recommends that compareTo be consistent with equals (because of the behavior in sorted sets or sorted maps).

I have a Player object which is mutable. Player will not be used in any kind of sorted set or sorted map.

I want to have an array of Players (Player[]) and assign each player a random order of play (a member variable m_nPlayOrder), then sort them in that array based on their m_nPlayOrder member variable.

I will implement the Comparable interface and the compareTo function to achieve this.

My question is, is it ok in this case if Player has a compareTo that is NOT consistant with equals? It will not be consistant with equals unless I also override equals (and hashCode) and have it return true if the Players m_nPlayerOrder are equal. I do not want to do that.

UPDATE: Thanks everyone for the replys! I'm going with implementing the Comparator instead of Comparable.

+3  A: 

You could implement a java.util.Comparator (a stand-alone object that "knows" your Player class and compares accordingly) and use that instead of implementing Comparable in the class.

Comparator has the advantage in that you can implement any number of them for different types of sorts, rather than the single Comparable.

Ash
I think that's the way to go. Comparator doc also says that "Caution should be exercised when using a comparator capable of imposing an ordering inconsistent with equals ", but I believe it is refering to the new Comparator class (not the Player class), am I correct?
cchampion
Probably if whatever makes use of your Comparator (the sort implementation) also relies on equals in some way, the inconsistency is a potential problem.
Ash
No, it is refering to the equals of the Player class, however the point is only that caution should be used (in case it is used as the comparitor in a sorted set that contains players), but the point is strictly about caution, not that you can't do it. You shoul indeed make such a comparator, and just document that it should not be used in the Collections framework.
Yishai
@Yishai - bad idea. Most developers simply don't expect this kind of inconsistency, and are not likely to look at the Javadocs to check. A good API design obeys the "Principal of Least Surprise".
Stephen C
@Stephen C, if the alternative is to create your own sorting algorithm, I'll go with reading the Java doc. BTW, I'm agreeing with your answer, so I'm not clear on what you are saying.
Yishai
@Yishai - my point is that it is a bad idea to say (as you appear to be saying) that "it is OK to have inconsistent equals/compareTo methods if you are cautious". Saying that is saying that bad design is OK. If that is not what you were saying ... then you were being unclear, and that is also dangerous.
Stephen C
@Stephen C, I don't see how you can see that from my comment. I was replying to "Caution should be exercised when using a comparator ..." to state that the equals in question is that of the Player, and that implementing the comparator (not comparable) should be done in this case, with caution.
Yishai
@Yishai - you actually used the phrase "however the point is only that caution should be used". It is your use of the word "only" that is the problem, because that is clearly NOT the only point that needs to be made.
Stephen C
+3  A: 

It is not a good practice to implement equals and compareTo that are inconsistent.

Player will not be used in any kind of sorted set or sorted map.

The problem is that someone else trying to maintain your code at some time in the future may not realize that you have implemented inconsistent methods, and may try to put a Player into a sorted set/map or some other data structure that expects consistent methods.

There is a good alternative available to you in the form of standalone Comparator objects.

Stephen C
+1  A: 

The Comparable API says, "It is strongly recommended (though not required) that natural orderings be consistent with equals." If you don't, be certain to document the limitations you noted. Alternatively, it may be easy to implement Comparable fully, as suggested in this answer.

trashgod
+2  A: 

I do not think you have the problem that you think you have, but perhaps I'm missing something (wouldn't be the first time).

The requirement here is that 2 objects that are equal should also return 0 for compareTo(), meaning that they occupy the same rank for sorting purposes. There is a separate requirement that 2 equal objects should also have the same hashCode. But this isn't a concern for you, because you're overriding neither equals() nor hashCode(); the Java platform will satisfy this one for you.

Since your objects will be equal based on reference comparison (not custom, logical comparison), you won't have a problem unless your objects don't compare to themselves. In orther words, as long as a single object, when asked to compareTo() itself, would always return 0, you're fine.

Drew Wills