我有一个类无法实现可比性,但需要根据2个字段进行排序。我怎样才能用番石榴来实现这个目标?
让我们说课程是:
class X {
String stringValue;
java.util.Date dateValue;
}
我有一份清单:
List<X> lotsOfX;
我想首先根据值字段对它们进行排序,然后根据“值”字段的每个“组”内的dateValue进行排序。
到目前为止我所做的是:
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应用程序中使用它。实施可比较不是一种选择。
答案 0 :(得分:21)
我怀疑你想要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);
答案 1 :(得分: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);
答案 2 :(得分:2)
Java 8为Comparator提供了简明扼要地指定链式比较器的方法。与新引入的List.sort一起,您可以:
lotsOfX.sort(
Comparator.comparingInt(x -> stringValueSortFunction.apply(x.stringValue))
.thenComparing(x -> x.dateValue, Comparator.reverseOrder()));
这会改变列表,当然 - 如果你想保持原始列表不变,先制作副本,或者将比较器包装在Ordering中,如果你想要一个不可变的副本,请使用immutableSortedCopy
。