Grundlefleck
Grundlefleck

Reputation: 129317

How to find which Comparator 'broke the tie' in a Guava Ordering

I use Guava's Ordering class to perfom sorting to pick the 'best' from a given list. It looks something like this:

// Create the Ordering, with a list of Comparators
Ordering<String> ranker = Ordering.compound(ImmutableList.of(
    STRING_LENGTH,
    PERCENTAGE_UPPERCASE,
    NUMBER_OF_VOWELS));

// Use the ordering to find the 'best' from a list of Strings
String best = ranker.max(asList("foo", "fooz", "Bar", "AEro"));

With this Ordering, the String "AEro" is the best because it's the longest, joint-best with "fooz", but tiebreaks with a higher percentage of uppercase characters.

I am looking for a way to tell which Comparator 'broke the tie', which in this silly contrived example would be the comparator PERCENTAGE_UPPERCASE.

I have a workable solution, but it's not particularly elegant, and means duplicating the list of Comparators. It is to use the Ordering to provide a sorted list (Ordering.sortedCopy), pulling the first two elements (range checking of course), iterating through a List of the same Comparators, comparing those two elements, breaking when the compareTo method returns non-zero result.

Is there a neater way?

Upvotes: 4

Views: 464

Answers (1)

Louis Wasserman
Louis Wasserman

Reputation: 198211

Guava contributor here.

Your solution seems like it's nearly as good as you're going to get, but instead of doing a sorted copy and pulling the first two elements, you should do the more efficient

List<E> best2 = ranker.greatestOf(list, 2);

and then, indeed, iterate through the comparators, though you can probably refactor so you're reusing the list of comparators from Ordering.compound, not recreating it.

Upvotes: 3

Related Questions