I think the problem is in your default case. Consider the set of nodes A, B, and C, where the IDs are 'a'
, 'b'
, and 'c'
. Consider further that your childMap
, which contains the relative ordering information, has the following contents:
{ 'a' => 1, 'c' => 3 }
Now if you run your compare
method on A and B, you return 0
, indicating that A and B are equivalent. Further, if you compare B and C, you still return 0
. However, if you compare A and C, then you return -1
, indicating that A is smaller. This violates the transitivity property of the Comparator contract:
The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0))
implies compare(x, z)>0
.
Finally, the implementor must ensure that compare(x, y)==0
implies that sgn(compare(x, z))==sgn(compare(y, z))
for all z
.
You can't treat "items which don't have an order assigned" as having the value "somewhere vaguely in the middle", since sorting algorithms don't know where to put them. If you want to stay with this approach, then in the case where the value is not present in the map, you need to assign a fixed value to be the ordering number; something like either 0
or MIN_INT
is a reasonable choice (but any choice needs to be documented in the Javadoc for compare
!).