ordering
guava ordering的使用
参考
官方说明文档-OrderingExplained
Guava强大的”流畅风格比较器”-翻译版
Guava —- Ordering排序工具-简单的使用
Guava学习笔记:Ordering犀利的比较器
概述
排序器Ordering是Guava流畅风格比较器Comparator的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。
从实现上说,Ordering实例就是一个特殊的Comparator实例。Ordering把很多基于Comparator的静态方法(如Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器。
简单使用
创建方式
Ordering.natural()
对可排序类型做自然排序,如数字按大小,日期按先后排序
List<integer> list = Arrays.asList(1, 5, 3, 8, 2);
collections.sort(list, Ordering.natural());
Ordering.usingToString
按对象的字符串形式做字典排序
List<String> listString = Lists.newArrayList("wang", "test", "a");
Collections.sort(listString, Ordering.usingToString());
Ordering.from(Comparator)
使预先存在的比较器进行排序
List<Worker> workers = Lists.newArrayList(worker, worker2, worker22, worker3);
Ordering<Worker> orderWorker = Ordering.from(new WorkerIdComparator());
Collections.sort(workers, orderWorker);
链式调用方法:通过链式调用,可以由给定的排序器衍生出其它排序器
reverse
获取语义相反的排序器
@Test
public void testOrderReverse() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
Collections.sort(list, Ordering.natural().reverse());
log.info("获取最大的元素" + Ordering.natural().max(list).toString());
log.info("排序后" + list.toString());
}
nullsFirst nullsLast
使用当前排序器,但额外把null值排到最前面,最后,原生的JDKCollections.sort会出现异常的,如果排序元素为空
原生调用
/**
* 排序中出现,空指针会异常的!
*/
@Test(expected = NullPointerException.class)
public void testJDKOrderIssue() {
List<Integer> list = Arrays.asList(1, 5, null, 3, 8, 2);
log.info("排序前" + list.toString());
Collections.sort(list); // 出现异常...
}
使用Guava Ordering
/**
* 将空值放置在最前面的情况
*/
@Test
public void testOrderNaturalByNullFirst() {
List<Integer> list = Arrays.asList(1, 5, null, 3, 8, 2);
Collections.sort(list, Ordering.natural().nullsFirst());
log.info("空在最前面-排序后" + list.toString());
}
多字段排序 compound(Comparator)
合成另一个比较器,以处理当前排序器中的相等情况。
public class WorkerIdComparator implements Comparator<Worker> {
@Override
public int compare(Worker worker1, Worker worker2) {
return Ints.compare(worker1.getWorkId(), worker2.getWorkId());
}
}
public class WorkerNameComparator implements Comparator<Worker> {
@Override
public int compare(Worker worker1, Worker worker2) {
return worker1.getName().compareTo(worker2.getName());
}
}
/**
* http://blog.csdn.net/wenniuwuren/article/details/46361119
* guava 多参数排序
* http://ifeve.com/Google-guava-ordering/
* Ordering.from 的使用
*/
@Test
public void testFrom() {
Worker worker = new Worker(1, "wangji");
Worker worker2 = new Worker(11, "guava");
Worker worker22 = new Worker(11, "aaa");
Worker worker3 = new Worker(111, "wangji3");
List<Worker> workers = Lists.newArrayList(worker, worker2, worker22, worker3);
Ordering<Worker> orderWorker = Ordering.from(new WorkerIdComparator());
Collections.sort(workers, orderWorker);
log.info("单参数:" + workers.toString());
// compound 相等的情况下,考虑第二个参数进行比较
Ordering<Worker> orderManyWorker = Ordering.from(new WorkerIdComparator()).compound(new WorkerNameComparator()).reverse();
Collections.sort(workers, orderManyWorker);
log.info("多参数:" + workers.toString());
}
运用排序器:Guava的排序器实现有若干操纵集合或元素值的方法
isOrdered
判断可迭代对象是否已按排序器排序:允许有排序值相等的元素。
/**
* isOrdered(Iterable) 判断可迭代对象是否已按排序器排序:允许有排序值相等的元素。
*/
@Test
public void testOrderNatural() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
Collections.sort(list);
boolean order = Ordering.natural().isOrdered(list); //是否为按照这样的顺序排好序的!自然的排序
log.info("排好序的:" + (order == true ? "是的" : "不是"));
}
min(E, E),min(E, E, E, E…),min(Iterable)
返回两个参数中最小的那个。如果相等,则返回第一个参数。
返回多个参数中最小的那个。如果有超过一个参数都最小,则返回第一个最小的参数
返回迭代器中最小的元素。如果可迭代对象中没有元素,则抛出NoSuchElementException。
max同理,这样的操作节省了一点时间和精力
/**
* 返回元素中的最大的值,同理最小的
*/
@Test
public void testMax() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
log.info("获取最大的元素" + Ordering.natural().max(list).toString()); //获取最大的元素8
log.info("获取最大的元素" + Ordering.natural().reverse().max(list).toString());//获取最大的元素1
}
greatestOf
获取可迭代对象中最大的k个元素,简化我们的操作的工作量
/**
* 返回一个排序对象中的最大的多少个元素-是不稳定的。
*/
@Test
public void testGreaTestOf() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
List<Integer> listMaxtOfK = Ordering.natural().greatestOf(list, 3);//获取可迭代对象中最大的k个元素。
log.info("获取最大的k个元素:" + listMaxtOfK.toString());
List<Integer> listMaxtOfMinik = Ordering.natural().reverse().greatestOf(list, 3);
// listMaxtOfK.add(1); UnmodifiableCollection 返回的是不可变对象,不可以进行操作
log.info("获取最大的Minik个元素:" + listMaxtOfMinik.toString());
}
sortedCopy(Iterable) immutableSortedCopy(Iterable)
复制排序后的元素的副本,不过这里不是深复制,需要保证集合元素中的不可变性,返回可变的集合元素和不可变的集合元素
/**
* 复制一个副本,这里没有进行集合元素的深复制,需要保证集合对象中为不可变对象
* 这里可以通过sortedCopy,返回一个可变的对象,immutableSortedCopy返回一个不可变的对象
*/
@Test
public void testSortedCopy() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
List<Integer> duplicateList = Ordering.natural().sortedCopy(list);// 返回一个副本
if (!Objects.equals(list, duplicateList)) {
log.info("返回的一个副本" + duplicateList.toString());
duplicateList.add(10);
log.info("返回的一个可变的副本" + duplicateList.toString());
}
List<Integer> duplicateImmutableList = Ordering.natural().immutableSortedCopy(list); // 返回一个不可变的副本
if (!Objects.equals(list, duplicateImmutableList)) {
log.info("返回的一个副本" + duplicateImmutableList.toString());
try {
duplicateImmutableList.add(10);
} catch (Exception e) {
log.info("返回的一个可变的副本不能添加");
}
}
}
所有的代码 guava 23.0
Orderexample
package guava.order;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* descrption: 排序的简单使用(Ordering是Guava流畅风格比较器Comparator的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。)
* authohr: wangji
* date: 2018-02-07 9:34
*/
@Slf4j
public class OrderExample {
@Test
public void testJDKOrder() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
log.info("排序前" + list.toString());
Collections.sort(list);
log.info("排序后" + list.toString());
}
/**
* 排序中出现,空指针会异常的!
*/
@Test(expected = NullPointerException.class)
public void testJDKOrderIssue() {
List<Integer> list = Arrays.asList(1, 5, null, 3, 8, 2);
log.info("排序前" + list.toString());
Collections.sort(list); // 出现异常...
}
/**
* 将空值放置在最前面的情况
*/
@Test
public void testOrderNaturalByNullFirst() {
List<Integer> list = Arrays.asList(1, 5, null, 3, 8, 2);
Collections.sort(list, Ordering.natural().nullsFirst());
log.info("空在最前面-排序后" + list.toString());
}
/**
* 将空值放置在最后面的情况
*/
@Test
public void testOrderNaturalByNullLast() {
List<Integer> list = Arrays.asList(1, 5, null, 3, 8, 2);
Collections.sort(list, Ordering.natural().nullsLast());
log.info("空在最后面-排序后" + list.toString());
}
/**
* isOrdered(Iterable) 判断可迭代对象是否已按排序器排序:允许有排序值相等的元素。
*/
@Test
public void testOrderNatural() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
Collections.sort(list);
boolean order = Ordering.natural().isOrdered(list); //是否为按照这样的顺序排好序的!自然的排序
log.info("排好序的:" + (order == true ? "是的" : "不是"));
}
/**
* reverse() 获取语义相反的排序器
*/
@Test
public void testOrderReverse() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
Collections.sort(list, Ordering.natural().reverse());
log.info("获取最大的元素" + Ordering.natural().max(list).toString());
log.info("排序后" + list.toString());
}
/**
* 返回元素中的最大的值,同理最小的
*/
@Test
public void testMax() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
log.info("获取最大的元素" + Ordering.natural().max(list).toString()); //获取最大的元素8
log.info("获取最大的元素" + Ordering.natural().reverse().max(list).toString());//获取最大的元素1
}
/**
* 返回一个排序对象中的最大的多少个元素-是不稳定的。
*/
@Test
public void testGreaTestOf() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
List<Integer> listMaxtOfK = Ordering.natural().greatestOf(list, 3);//获取可迭代对象中最大的k个元素。
log.info("获取最大的k个元素:" + listMaxtOfK.toString());
List<Integer> listMaxtOfMinik = Ordering.natural().reverse().greatestOf(list, 3);
// listMaxtOfK.add(1); UnmodifiableCollection 返回的是不可变对象,不可以进行操作
log.info("获取最大的Minik个元素:" + listMaxtOfMinik.toString());
}
/**
* natural():使用Comparable类型的自然顺序, 例如:整数从小到大,字符串是按字典顺序;
* usingToString() :使用toString()返回的字符串按字典顺序进行排序;
*/
@Test
public void testUsingToString() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
Collections.sort(list, Ordering.usingToString());
log.info("排序后" + list.toString());
List<String> listString = Lists.newArrayList("wang", "test", "a");
Collections.sort(listString, Ordering.usingToString());
log.info("排序后" + listString.toString());
}
/**
* 复制一个副本,这里没有进行集合元素的深复制,需要保证集合对象中为不可变对象
* 这里可以通过sortedCopy,返回一个可变的对象,immutableSortedCopy返回一个不可变的对象
*/
@Test
public void testSortedCopy() {
List<Integer> list = Arrays.asList(1, 5, 3, 8, 2);
List<Integer> duplicateList = Ordering.natural().sortedCopy(list);// 返回一个副本
if (!Objects.equals(list, duplicateList)) {
log.info("返回的一个副本" + duplicateList.toString());
duplicateList.add(10);
log.info("返回的一个可变的副本" + duplicateList.toString());
}
List<Integer> duplicateImmutableList = Ordering.natural().immutableSortedCopy(list); // 返回一个不可变的副本
if (!Objects.equals(list, duplicateImmutableList)) {
log.info("返回的一个副本" + duplicateImmutableList.toString());
try {
duplicateImmutableList.add(10);
} catch (Exception e) {
log.info("返回的一个可变的副本不能添加");
}
}
}
}
多字段排序
@Slf4j
public class Worker {
private Integer workId;
private String name;
public Integer getWorkId() {
return workId;
}
public void setWorkId(Integer workId) {
this.workId = workId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Worker(Integer workId, String name) {
this.workId = workId;
this.name = name;
}
@Override
public String toString() {
return "Worker{" +
"workId=" + workId +
", name='" + name + '\'' +
'}';
}
}
package guava.order;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* descrption: 使用自定义排序规则、多字段排序
* authohr: wangji
* date: 2018-02-07 10:21
*/
@Slf4j
public class OrderExample2 {
public class WorkerIdComparator implements Comparator<Worker> {
@Override
public int compare(Worker worker1, Worker worker2) {
return Ints.compare(worker1.getWorkId(), worker2.getWorkId());
}
}
public class WorkerNameComparator implements Comparator<Worker> {
@Override
public int compare(Worker worker1, Worker worker2) {
return worker1.getName().compareTo(worker2.getName());
}
}
/**
* http://blog.csdn.net/wenniuwuren/article/details/46361119
* guava 多参数排序
* http://ifeve.com/google-guava-ordering/
* Ordering.from 的使用
*/
@Test
public void testFrom() {
Worker worker = new Worker(1, "wangji");
Worker worker2 = new Worker(11, "guava");
Worker worker22 = new Worker(11, "aaa");
Worker worker3 = new Worker(111, "wangji3");
List<Worker> workers = Lists.newArrayList(worker, worker2, worker22, worker3);
Ordering<Worker> orderWorker = Ordering.from(new WorkerIdComparator());
Collections.sort(workers, orderWorker);
log.info("单参数:" + workers.toString());
// compound 相等的情况下,考虑第二个参数进行比较
Ordering<Worker> orderManyWorker = Ordering.from(new WorkerIdComparator()).compound(new WorkerNameComparator()).reverse();
Collections.sort(workers, orderManyWorker);
log.info("多参数:" + workers.toString());
}
}
多看学、多总结
相关阅读
目录 【基本工具】一、Optional 针对Java开发中null的问题,guava设计了Optional类。虽然util包下也有自带的Optional类,但是
扯淡一下:刚刚换了新工作,新的公司,新的同事,很好的伙伴们,都很喜欢;新的业务,新的技术,新的挑战:开启新的旅程,Fighting! 这阵子一直了解