13

我有一个类无法实现可比性,但需要根据 2 个字段进行排序。我怎样才能用番石榴做到这一点?

假设课程是:

class X {
  String stringValue;
  java.util.Date dateValue;
} 

我有一个清单:

List<X> lotsOfX;

我想首先根据 value 字段对它们进行排序,然后根据 dateValue 在“value”字段的每个“组”中降序排列。

到目前为止我一直在做的是:

List<X> sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(dateValueSortFunction).reverse().sortedCopy(lotsOfX));
sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(stringValueSortFunction).sortedCopy(sortedList));

函数定义为:

public class DateValueSortFunction<X> implements Function<X, Long> {

    @Override
      public Long apply(X input) {
        return input.getDateValue().getTime();  //returns millis time
      }
}

和:

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;
        }
}

预期输出sortedList为:

Something   03/18/2013
Something   03/17/2013
Something else  03/20/2013
Something else  03/19/2013
....

我的方法有效,但对于遍历列表两次显然效率低下。有没有更好的方法来做到这一点?

我在 GWT 应用程序中使用它。实施可比较不是一种选择。

4

3 回答 3

24

我怀疑你想要Ordering.compound. 您可以在一个语句中完成所有操作,但我会使用:

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);
于 2013-03-20T19:31:48.200 回答
17

一个功能较少但可以说更清洁的解决方案:

new Ordering<X>() {
  public int compare(X x1, X x2) {
    return ComparisonChain.start()
      .compare(x1.stringValue, x2.stringValue)
      .compare(x2.dateValue, x1.dateValue) // flipped for reverse order
      .result();
  }
}.immutableSortedCopy(listOfXs);
于 2013-03-20T19:54:10.177 回答
2

Java 8 在 Comparator 上提供了方法来简洁地指定链式比较器。与新引入的 List.sort 一起,您可以:

lotsOfX.sort(
    Comparator.comparingInt(x -> stringValueSortFunction.apply(x.stringValue))
        .thenComparing(x -> x.dateValue, Comparator.reverseOrder()));

当然,这会改变列表 - 如果您想保持原始列表不变,请先制作副本,或者将比较器包装在 Ordering 中,immutableSortedCopy如果您想要不可变的副本,请使用。

于 2014-10-04T23:59:51.737 回答