(Guava 译文系列)排序

排序

示例

1
assertTrue(byLengthOrdering.reverse().isOrdered(list));

简述

Ordering是 Guava 的“流式”Comparator类。它能够用于构建复杂的比较器,并且能应用于集合对象上。

一个Ordering实例的核心仅仅是一个特殊的Comparator实例。Ordering简单的取用一些依赖Comparator的静态方法(例如 Collections.max)将之改造为实例方法。此外,Ordering类还提供了链式方法来改进、增强现有的比较器。

创建

通用的排序实例可由静态方法提供:

方法 描述
natural 使用正常序列的 Comparable 类型
usingToString 以字典序对对象的字符串表示(由toString()返回)进行排序

将一个现存的Comparator来构造Ordering,最简单的方法是使用Ordering.from(Comparator)

但是更通用的构造一个自定义Ordering的方法是完全跳过Comparator而直接扩展Ordering的抽象类:

1
2
3
4
5
Ordering<String> byLengthOrdering = new Ordering<String>() {
public int compare(String left, String right) {
return Ints.compare(left.length(), right.length());
}
};

链式调用

一个给定的Ordering可以被包装并获取派生的Ordering。如下是一些最常用的变体:

方法 描述
reverse() 返回反向排序
nullsFirst() 返回一个新的Ordering,会将 null 对象至于 non- null 对象之前,如果没有 null 对象,则表现为与原始Ordering的行为一致。类似的可见nullsLast
compound(Comparator) 返回一个专用的Ordering,当遇到相等情况时可进行进一步比较
lexicographical() 返回可对 iterables 的元素按照字典序排序的Ordering
onResultOf(Function) 返回一个Ordering,对被比较值先执行 Function,对返回值按初始Ordering进行排序

举例说明,假如你想要构造一个下述类的比较器:

1
2
3
4
class Foo {
@Nullable String sortedBy;
int notSortedBy;
}
该比较器能处理可为 null 的sortBy成员。以下是一个建立在链式调用方法上的解决方案:
1
2
3
4
5
Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(new Function<Foo, String>() {
public String apply(Foo foo) {
return foo.sortedBy;
}
});
当链式调用的Ordering进行读取时,按从右至左倒序工作。以上例子通过读取sortedBy成员变量值来对Foo进行排序,首先将所有为 null 的sortedBy移动至最前面,然后对剩下的进行字符串的正常排序。之所以出现倒序,是因为每一个链式调用,都将上一个Ordering进行封装成为一个新的Ordering

(对“倒序”规则的一个例外:当链式调用涉及compound时,读取从左至右。为了避免混淆,不要将compound与其他类型的链式调用一起使用。)

超过几个调用的调用链将会难以理解。就像上述例子一样,我们推荐限制链式调用的调用长度不大于 3 个。即使这样,你也许会期望进一步简化,将 中间对象 - 如Function实例 - 分离出来,就像这样:

1
Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(sortKeyFunction);

应用

Guava 提供了许多方法来通过Ordering对值或集合进行操作或检查。我们在以下列出了最常用的:

方法 描述 类似的
greatestOf(Iterable iterable, int k) 返回指定 iterable 中k个最大的元素,按照该Ordering从大到小排序 leastOf
isOrdered(Iterable) 测试指定的 Iterable 是否按照Ordering非递减排序。 isStrictlyOrdered
sortedCopy(Iterable) 返回一个对指定元素进行排序的副本List immutableSortedCopy
min(E, E) 按照Ordering返回输入参数中较小的一个。假如相等,则返回第一个 max(E, E)
min(E, E, E, E...) 按照Ordering返回输入参数中较小的一个。假如存在多个最小值,则返回第一个 max(E, E, E, E...)
min(Iterable) 返回指定Iterable中最小的元素。假如Iterable为空则抛出NoSuchElementException异常 max(Iterable), min(Iterator), max(Iterator)