使用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