Java 集合排序策略接口 Comparator
1. 前言
最近用到了集合排序(基于 Java 8)。现在我能用 Stream 的就用 Stream ,真香!排序可以这么写:
List<People> peoples = new ArrayList<>();
// 中间省略
// 按照年龄从小到大排序
peoples.sort(Comparator.comparing(People::getAge));
这里排序用到了一个关键接口 java.util.Comparator
。排序比较作为业务中经常出现的需求,我们有必要研究一下这个接口。
2. Comparator 概念
Comparator
是一个函数式接口。它经常用于没有天然排序的集合进行排序,如 Collections.sort
或 Arrays.sort
。或者对于某些有序数据结构的排序规则进行声明,如 TreeSet
、TreeMap
。也就是该接口主要用来进行集合排序。
3. Comparator 中的方法
Comparator
作为一个函数式接口只有一个抽象方法,但是它有很多的默认方法,我们来认识一下这些方法们。
3.1 compare 抽象方法
作为Comparator
唯一的抽象方法,int compare(T o1,T o2)
比较两个参数的大小, 返回负整数,零,正整数 ,分别代表 o1<o2
、o1=o2
、o1>o2
,通常分别返回 -1
、0
或 1
。伪表达式:
// 输入两个同类型的对象 ,输出一个比较结果的int数字
(x1,x2)-> int
实现该方法一定要注意以下事项:
- 必须保证
compare(x,y)
和compare(y,x)
的值的和必须为 0 。 - 必须保证比较的顺序关系是可传递的,如果
compare(x,y)>0
而且compare(y,z)>0
则compare(x,z)>0
。 - 如果存在
compare(x,y)=0
,则对于z
而言,存在compare(x, z)==compare(y, z)
。
然而并不 严格要求
(compare(x, y)==0) == (x.equals(y))
。一般说来,任何违背这个条件的 Comparator 实现都应该明确指出这一事实情况。
3.2 comparing 系列方法
从 Java 8 开始,Comparator
提供了一系列的静态方法,并通过函数式的风格赋予 Comparator
更加强大和方便的功能,我们暂且称它们为 comparing
系列方法。
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
该方法是该系列方法的基本方法。是不是看上去很难懂的样子?我们来分析一下该方法。它一共两个参数都是函数式接口。
第一个参数 Function<? super T, ? extends U> keyExtractor
表示输入一个是 T
类型对象,输出一个 U
类型的对象,举个例子,输入一个 People
对象返回其年龄 Integer
数值:
// people -> people.getAge(); 转换为下面方法引用
Function<People, Integer> getAge = People::getAge;
第二个参数 keyComparator
就很好理解了,表示使用的比较规则。
对 c1
,c2
按照 第一个参数 keyExtractor
提供的规则进行提取特征,然后第二个参数keyComparator
对这两个特征进行比较。下面的式子其实可以概括为 3.1 的 (x1,x2)-> int
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2))
Comparator & Serializable 为 Java 8 新特性:同时满足这两个类型约束
理解了这个方法后,其它该系列的方法就好理解了,这里不再赘述。目前 comparing
系列方法使用更加广泛。我们举一些例子:
List<People> peoples = new ArrayList<>();
// ………………
// 按照年龄从低到高排序
peoples.sort(Comparator.comparing(People::getAge));
// 按照年龄从高到低排序
peoples.sort(Comparator.comparing(People::getAge, (x, y) -> -x.compareTo(y)));
同样你可以使用
java.util.Collections
或者Stream
提供的排序方法来使用Comparator
。
4. 小结
今天对 Comparator
进行了简单的分析,它用于构建集合排序的规则,在日常开发中非常有用。下一篇 我们将对另一个和它十分相似的接口 Comparable
进行分析和比较它们的不同,敬请关注。
关注公众号:Felordcn 获取更多资讯
Java 集合排序策略接口 Comparator的更多相关文章
- Java集合Map接口与Map.Entry学习
Java集合Map接口与Map.Entry学习 Map接口不是Collection接口的继承.Map接口用于维护键/值对(key/value pairs).该接口描述了从不重复的键到值的映射. (1) ...
- java集合类型接口和实现类个人总结
转载:http://blog.csdn.net/qingchunbusanchang/article/details/39576749 java的集合是一个比较综合的概念,相关的知识有很多的博客里面做 ...
- JAVA集合--Iterator接口
本文首发于cartoon的博客 转载请注明出处:https://cartoonyu.github.io/cartoon-blog 上一篇文章中我在集合元素的遍历中已经有涉及到I ...
- JAVA集合--Collection接口
本文首发于cartoon的博客 转载请注明出处:https://cartoonyu.github.io/cartoon-blog 在概述里面也说过:Collection是jav ...
- Java集合——Set接口
1.定义 set中不允许放入重复的元素(元素相同时只取一个),使用equals()方法进行比较.如果返回true,两个对象的HashCode值也应该相等 2.方法 add():添加元素 remove( ...
- Java集合-07Map接口及其抽象类
简介 前面把List基本记录完了,对于集合List,Map,Set,因为Set基于Map,故先记录Map. 这一篇主要记录Map接口及其抽象类(java version:1.8) 整体架构 参考上图, ...
- java集合——Collection接口
Collection是Set,List接口的父类接口,用于存储集合类型的数据. 2.方法 int size():返回集合的长度 void clear():清除集合里的所有元素,将集合长度变为0 Ite ...
- Java集合——Map接口
1.定义 Map用于保存存在映射关系<key,value>的数据.其中,key值不能重复(使用equals()方法比较),value值可以重复 2.方法 V put(key,value) ...
- Java集合——List接口
1.定义 List是Collection的子接口,元素有序并且可以重复,表示线性表. 2.方法 add(int index,Object e):在指定索引(和数组下标类似,为0,1,2....)放入元 ...
随机推荐
- java 多线--静态代理模式
我们使用 java 多线程时,都需要通过线程代理对象来启动线程,常见的写法: new Thread(target).start(); 这在设计模式中叫静态代理模式,静态代理模式组成; 1.公共接口 2 ...
- Nginx知多少系列之(十四)Linux下.NET Core项目Nginx+Keepalived高可用(主从模式)
目录 1.前言 2.安装 3.配置文件详解 4.工作原理 5.Linux下托管.NET Core项目 6.Linux下.NET Core项目负载均衡 7.负载均衡策略 8.加权轮询(round rob ...
- Ubuntu16.04 安装eclipse
首先确保自己的Ubuntu已经安装了jdk并且配置好了环境变量 然后在官网下载相应的eclipse安装包: https://www.eclipse.org/downloads/packages/ 下载 ...
- (第三篇)SSH网络协议概述
ssh简介原理 windows远程登录,QQ远程协助修电脑 简单说,SSH是一种网络协议,用于计算机之间的加密登录.最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑.1995年,芬兰学者 ...
- Spring Cloud sleuth with zipkin over RabbitMQ教程
文章目录 Spring Cloud sleuth with zipkin over RabbitMQ demo zipkin server的搭建(基于mysql和rabbitMQ) 客户端环境的依赖 ...
- 【Linux网络基础】网络子网划分基础知识(IP地址,子网)
一. IP地址分类与子网划分基础 1. 什么是IP地址? 常见的ip地址版本为ipv4, ipv6 32位 4 * 8=32位. 32位二进制数字序列组成的数字序列 点分十进制 采用点将32位数字 ...
- mac OS 安装 Homebrew软件包管理器
Homebrew macOS 缺失的软件包的管理器 中文官网 https://brew.sh/index_zh-cn 获取安装命令 /usr/bin/ruby -e "$(curl -fsS ...
- VS中的生成和重新生成的区别
2019独角兽企业重金招聘Python工程师标准>>> 生成 在上次编译的基础上,只对改动过的文件重新生成,没有改动过的文件不会重新生成. 重新生成 对所有的文件都重新生成.如果引用 ...
- predixy源码学习
Predixy是一个代理,代理本质上就是用来转发请求的.其主要功能就是接收客户端的请求,然后把客户端请求转发给redis服务端,在redis服务端处理完消息请求后,接收它的响应,并把这个响应返回给客户 ...
- css的属性选择器
语法说明: 属性选择器需要将对应属性放入到 方括号中 [ ] ,其中包含属性名,标识符(* $ ~ ^ |) 使用说明: [attribute] 例如 [target] 表示 选择带有 targe ...