Reputation: 129317
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 Comparator
s. 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 Comparator
s, comparing those two elements, breaking when the compareTo
method returns non-zero result.
Is there a neater way?
Upvotes: 4
Views: 464
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