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