专栏首页码农小胖哥的码农生涯Java 集合排序规则接口 Comparator

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.sortArrays.sort或者对于某些有序数据结构的排序规则进行声明,如 TreeSetTreeMap 。也就是该接口主要用来进行集合排序。

3. Comparator 中的方法

Comparator 作为一个函数式接口只有一个抽象方法,但是它有很多的默认方法,我们来认识一下这些方法们。

3.1 compare 抽象方法

作为Comparator 唯一的抽象方法,int compare(T o1,T o2) 比较两个参数的大小, 返回负整数,零,正整数 ,分别代表 o1<o2o1=o2o1>o2,通常分别返回 -101。伪表达式:

// 输入两个同类型的对象 ,输出一个比较结果的int数字
(x1,x2)-> int

实现该方法一定要注意以下事项:

  • 必须保证compare(x,y)compare(y,x) 的值的和必须为 0
  • 必须保证比较的顺序关系是可传递的,如果compare(x,y)>0 而且compare(y,z)>0compare(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),作者:码农小胖哥

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JDK12 Collectors.teeing 功能真香

    在 Java 12 里面有个非常好用但在官方 JEP 没有公布的功能,因为它只是 Collector 中的一个小改动,它的作用是 merge 两个 collec...

    码农小胖哥
  • Spring Security 实战干货:如何实现不同的接口不同的安全策略

    欢迎阅读 Spring Security 实战干货 系列文章 。最近有开发小伙伴提了一个有趣的问题。他正在做一个项目,涉及两种风格,一种是给小程序出接口,安全上...

    码农小胖哥
  • Nginx(二)-- 配置文件之虚拟主机配置

    1) 在nginx/conf/nginx.conf文件中的http段中添加一个server,如下所示:

    码农小胖哥
  • 有钱没命花的保罗和扛不住八个明星出轨的新浪

    这几天在国内飞了好几个城市,非常的繁忙,也没有时间更新公众号。我想如果我生活工作在国内,是很难把飞总聊IT的公众号做到这么大,写了那么多文章的,国内的工作节奏是...

    用户1564362
  • 设计之禅——适配器模式

    对于适配器相信大家不会陌生,生活中有各种各样的例子,像耳机转接线,充电器适配器,水管适配接口等等。通过类比我们很容易理解适配器的作用:

    夜勿语
  • Charles使用笔记

    Charles本身其实是一款十分强大且易用的代理软件,最近用的比较多,大致整理了一下自己用到的一些东西。

    木子墨
  • python selenium自动登录web浏览器

    https://addons.mozilla.org/zh-CN/firefox/ katalon(推荐)、selenium IDE

    以谁为师
  • 浅谈ViewModel

    1 主要功能 Activity、Fragment存活期间的数据存储; bind同一Activity的多个Fragment间数据共享; 独立或与LiveData...

    QQ音乐技术团队
  • Rafy 框架-发布网页版用户手册

    前段时间把 Rafy 的用户手册由 CHM 格式转换为了网页格式,而且发布到了 github.io 上,即方便文档的实时更新,也方便大家查看。 Rafy 用户手...

    用户1172223
  • 如何输出一份专业优秀的交互文档?

    在项目设计中,交互设计师与上游的产品经理,下游的视觉设计师,开发工程师和测试等岗位的工作密不可分。不论是承上启下的工作沟通, 还是方案评审的设计讲解,专业的交互...

    前朝楚水

扫码关注云+社区

领取腾讯云代金券