(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 | Ordering<String> byLengthOrdering = new Ordering<String>() { |
链式调用
一个给定的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
4class Foo {
String sortedBy;
int notSortedBy;
}sortBy成员。以下是一个建立在链式调用方法上的解决方案:
1
2
3
4
5Ordering<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) |