I have a class WHICH CANNOT implement comparable, but needs to be sorted based on 2 fields. How can I achieve this with Guava?
Let's say the class is:
class X {
String stringValue;
java.util.Date dateValue;
}
And I have a list of these:
List<X> lotsOfX;
I want to sort them based on the value field first and then based on dateValue descending within each 'group' of 'value' fields.
What I have been doing so far is:
List<X> sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(dateValueSortFunction).reverse().sortedCopy(lotsOfX));
sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(stringValueSortFunction).sortedCopy(sortedList));
The functions are defined as:
public class DateValueSortFunction<X> implements Function<X, Long> {
@Override
public Long apply(X input) {
return input.getDateValue().getTime(); //returns millis time
}
}
And:
public class StringValueSortFunction<X> implements Function<X, Integer> {
@Override
public Integer apply(X input) {
if(input.getStringValue().equalsIgnoreCase("Something"))
return 0;
else if(input.getStringValue().equalsIgnoreCase("Something else"))
return 1;
else
return 2;
}
}
Expected output in sortedList
is:
Something 03/18/2013
Something 03/17/2013
Something else 03/20/2013
Something else 03/19/2013
....
My approach works but is obviously inefficient for traversing the list twice. Is there a better way of doing this?
I am using this in a GWT app. Implementing comparable is not an option.
I suspect you want Ordering.compound
. You could do it all in one statement, but I'd use:
Ordering<X> primary = Ordering.natural().onResultOf(stringValueSortFunction);
Ordering<X> secondary = Ordering.natural()
.onResultOf(dateValueSortFunction)
.reverse();
Ordering<X> compound = primary.compound(secondary);
List<X> sortedList = compound.immutableSortedCopy(lotsOfX);
Java 8 provides methods on Comparator to concisely specify chained comparators. Together with the newly-introduced List.sort, you can do:
lotsOfX.sort(
Comparator.comparingInt(x -> stringValueSortFunction.apply(x.stringValue))
.thenComparing(x -> x.dateValue, Comparator.reverseOrder()));
This mutates the list, of course -- make a copy first if you want to leave the original list unchanged, or wrap the comparator in an Ordering and use immutableSortedCopy
if you want an immutable copy.
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