使用Guava Ordering对对象列表进行多标准排序
我有一个类无法实现可比性,但需要根据2个字段进行排序。 我怎样才能用番石榴来实现这个目标?
让我们说课程是
class X { String stringValue; java.util.Date dateValue; }
我有一份清单
List lotsOfX;
我想先根据值字段对它们进行排序,然后根据每个’组’的’value’字段中的dateValue进行排序。
到目前为止我一直在做的是
List sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(dateValueSortFunction).reverse().sortedCopy(lotsOfX)); sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(stringValueSortFunction).sortedCopy(sortedList));
function定义为:
public class DateValueSortFunction implements Function { @Override public Long apply(X input) { return input.getDateValue().getTime(); //returns millis time } }
和
public class StringValueSortFunction implements Function { @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应用程序中使用它。 实施可比较不是一种选择。
我怀疑你想要Ordering.compound
。 你可以在一个声明中完成所有操作,但我会使用:
Ordering primary = Ordering.natural().onResultOf(stringValueSortFunction); Ordering secondary = Ordering.natural() .onResultOf(dateValueSortFunction) .reverse(); Ordering compound = primary.compound(secondary); List sortedList = compound.immutableSortedCopy(lotsOfX);
function较少但可以说更清洁的解决方案:
new Ordering() { 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);
Java 8为Comparator提供了简明地指定链式比较器的方法。 与新推出的List.sort一起,您可以:
lotsOfX.sort( Comparator.comparingInt(x -> stringValueSortFunction.apply(x.stringValue)) .thenComparing(x -> x.dateValue, Comparator.reverseOrder()));
当然,这会改变列表 – 如果要保持原始列表不变,请首先制作副本,或者将比较器包装在Ordering中,如果需要不可变副本,请使用immutableSortedCopy
。