1. 概述
在这篇文章中,我们将探讨Guava库中的Ordering
类。
Ordering
类实现了Comparator
接口,并为我们提供了创建和链式组合比较器的有用 fluent API。
顺便提一下,值得了解一下Java新引入的Comparator.comparing()
方法——它提供了类似的功能;这里有一个使用该API的实用示例:Java 8 排序 lambda。
2. 创建Ordering
Ordering
类提供了一个有用的构建器方法,返回一个可用于在集合的sort()
方法或其他需要Comparator
实例的地方使用的适当实例。
我们可以通过调用natural()
方法来创建自然顺序的实例:
List<Integer> integers = Arrays.asList(3, 2, 1);
integers.sort(Ordering.natural());
assertEquals(Arrays.asList(1,2,3), integers);
假设我们有一个Person
对象的集合:
class Person {
private String name;
private Integer age;
// standard constructors, getters
}
如果我们想按age
字段对这样的对象列表进行排序,可以通过扩展它来创建自定义的Ordering
:
List<Person> persons = Arrays.asList(new Person("Michael", 10), new Person("Alice", 3));
Ordering<Person> orderingByAge = new Ordering<Person>() {
@Override
public int compare(Person p1, Person p2) {
return Ints.compare(p1.age, p2.age);
}
};
persons.sort(orderingByAge);
assertEquals(Arrays.asList(new Person("Alice", 3), new Person("Michael", 10)), persons);
然后我们可以使用orderingByAge
并将其传递给sort()
方法。
3. 链接Orderings
这个类的一个有用特性是我们可以链式地应用不同的排序方式。例如,我们有一个Person
对象的集合,想要按age
字段排序,并且将age
字段为null
的对象放在列表的开头:
List<Person> persons = Arrays.asList(
new Person("Michael", 10),
new Person("Alice", 3),
new Person("Thomas", null));
Ordering<Person> ordering = Ordering
.natural()
.nullsFirst()
.onResultOf(new Function<Person, Comparable>() {
@Override
public Comparable apply(Person person) {
return person.age;
}
});
persons.sort(ordering);
assertEquals(Arrays.asList(
new Person("Thomas", null),
new Person("Alice", 3),
new Person("Michael", 10)), persons);
这里需要注意的是特定Ordering
执行的顺序——从右到左。首先,onResultOf()
方法被执行,该方法提取我们想要比较的字段。
接着,nullFirst()
比较器被应用。因此,排序后的集合将把age
字段为null
的Person
对象放在列表的开头。
排序过程的最后,使用natural()
方法指定的自然顺序来比较age
字段。
4. 总结
在这篇文章中,我们研究了Guava库中的Ordering
类,它使我们能够创建更流畅、优雅的Comparator
。我们创建了自定义的Ordering
,使用了API中预定义的,还通过链式操作以实现更定制的排序。
所有这些示例和代码片段的实现可以在GitHub项目中找到——这是一个基于Maven的项目,可以直接导入并运行,无需额外配置。