guava是谷歌开源的一套Java类库,非常实用优雅。
Ordering继承了Comparator接口,它提供了流式的API,用于构建复杂的比较器:
package org.lin.learn;
import java.util.ArrayList;
import java.util.Collections;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
public class GuavaOrdering {
public static void main(String[] args) {
//构造一个比较器,先根据字符串长度排序,再按照字典序排序,null值置前
Ordering ordering = Ordering.natural()
.onResultOf((String str) -> {
//使用Optional处理null值
return Optional.fromNullable(str).or("").length();
})
.compound(Ordering.natural().nullsFirst()); //compound用于合并两个Ordering
ArrayList names = Lists.newArrayList("Ram", "Shyam", "Mohan", "Sohan",
"Ramesh", "Suresh", "Naresh", "Mahesh", null, "", "Vikas", "Deepak");
Collections.sort(names, ordering);
System.out.println(names);
}
}
输出结果:
源码分析:
每次的链式调用,都会用后者包装前者的方式返回一个新的Ordering对象,如nullsFirst方法:
可以看到NullsFirstOrdering先用自己的逻辑比较,再用之前的比较器比较,所以链式调用的代码应该从后往前看。
但compound是个例外:
基于上面的代码:
System.out.println("最大的4个元素,从大到小:" + ordering.greatestOf(names, 4));
System.out.println("最小的4个元素,从小到大:" + ordering.leastOf(names, 4));
System.out.println("最大值:" + ordering.max(names));
System.out.println("最小值:" + ordering.min(names));
输出:
如果看Ordering源码,注释写道,在Java8中Ordering已经过时了,因为大部分方法在Comparator中已经实现了!其他的方法可以在guava的Comparators工具类中找到。
所以在Java8中,写法应该是:
package org.lin.learn;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Optional;
import com.google.common.collect.Comparators;
import com.google.common.collect.Lists;
public class Java8Sorting {
public static void main(String[] args) {
ArrayList names = Lists.newArrayList("Ram", "Shyam", "Mohan", "Sohan",
"Ramesh", "Suresh", "Naresh", "Mahesh", null, "", "Vikas", "Deepak");
Comparator comparator =
Comparator.comparing((str) -> {
//这是Java8的Optional
return Optional.ofNullable(str).orElse("").length();
})
.thenComparing(Comparator.nullsFirst(Comparator.naturalOrder()));
names.sort(comparator);
System.out.println(names);
System.out.println("最大的四个元素:" + names.stream().collect(Comparators.greatest(4, comparator)));
System.out.println("最小的四个元素:" + names.stream().collect(Comparators.least(4, comparator)));
System.out.println("最大的元素:" + names.stream().max(comparator).get());
//遗憾的是,min内部使用Optional.of,null元素会抛空指针异常
System.out.println("最小的元素:" + names.stream().min(comparator).get());
}
}
输出:
guava的Ordering和Optional,在Java8之前拥有非常先进的理念,它借助链式调用的方式,模拟了函数式编程,但在Java8之后,Ordering和guava的Optional可以说已经过时,取而代之的是Java强大的stream API 和 Comparator接口。得益于interface默认方法的支持,大部分Ordering的方法Comparator和Stream API已经实现了。
函数式编程:
1.以函数作为参数,Java中是传递函数式接口的对象,表现为匿名内部类或者Lambda表达式,也可以是方法引用
2.函数的链式调用,前一个函数的结果作为下一个函数的输入,在Java中表现为方法的链式调用
参考:
Java排序增强,方法引用
目前guava的类库只接触了小部分,给我的感觉是jdk,还有其他的开源框架,在很多地方借鉴了guava的思想,继续接触期待有其他发现。