How to implement java.util.Comparator
that orders its elements according to a partial order relation?
For example given a partial order relation a ≺ c, b ≺ c; the order of a and b is undefined.
Since Comparator
requires a total ordering, the implementation orders elements for which the partial ordering is undefined arbitrarily but consistent.
Would the following work?
interface Item {
boolean before(Item other);
}
class ItemPartialOrderComperator implements Comparator<Item> {
@Override
public int compare(Item o1, Item o2) {
if(o1.equals(o2)) { // Comparator returns 0 if and only if o1 and o2 are equal;
return 0;
}
if(o1.before(o2)) {
return -1;
}
if(o2.before(o1)) {
return +1;
}
return o1.hashCode() - o2.hashCode(); // Arbitrary order on hashcode
}
}
Comparators
required to be transitive?TreeMap
)
A partial order is “partial” because there can be two elements with no relation between them. For example, in the “divides” partial order on f1; 2; : : : ; 12g, there is no relation between 3 and 5 (since neither divides the other). In general, we say that two elements a and b are incomparable if neither a b nor b a.
A partial order relation is a homogeneous relation that is transitive and antisymmetric. There are two common sub-definitions for a partial order relation, for reflexive and irreflexive partial order relations, also called "non-strict" and "strict" respectively.
A relation R on a set A is called a partial order relation if it satisfies the following three properties: Relation R is Reflexive, i.e. aRa ∀ a∈A. Relation R is Antisymmetric, i.e., aRb and bRa ⟹ a = b. Relation R is transitive, i.e., aRb and bRc ⟹ aRc.
This definition says that in a total order any two things are comparable. Wheras in a partial order a thing needs neither to be "smaller" than an other nor the other way around, in a total order each thing is either "smaller" than an other or the other way around.
The problem is that, when you have incomparable elements, you need to fall back to something cleverer than comparing hash codes. For example, given a partial order {a < b, c < d}, the hash codes could satisfy h(d) < h(b) < h(c) < h(a), which means that a < b < c < d < a (bold denotes tie broken by hash code), which will cause problems with a TreeMap
.
In general, there's probably nothing for you to do except topologically sort the keys beforehand, so some details about the partial orders of interest to you would be welcome.
It seems to be more of an answer than a comment so I'll post it
The documentation says:
It follows immediately from the contract for compare that the quotient is an equivalence relation on S, and that the imposed ordering is a total order on S."
So no, a Comparator requires a total ordering. If you implement this with a partial ordering you're breaching the interface contract.
Even if it might work in some scenario, you should not attempt to solve your problem in a way that breaches the contract of the interface.
See this question about data structures that do fit a partial ordering.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With