Java8 Comparator: 列表排序的深入讲解

在本文中,我们将看到几个关于如何在Java 8中对List进行排序的示例。

1.按字母顺序排序字符串列表

List<String> cities = Arrays.asList(
  "Milan",
  "london",
  "San Francisco",
  "Tokyo",
  "New Delhi"
);
System.out.println(cities);
//[Milan, london, San Francisco, Tokyo, New Delhi]
cities.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println(cities);
//[london, Milan, New Delhi, San Francisco, Tokyo]
cities.sort(Comparator.naturalOrder());
System.out.println(cities);
//[Milan, New Delhi, San Francisco, Tokyo, london]

为了更加突出显示Comparator.naturalOrder() (返回按照大小写字母排序的Comparator)和String.CASE_INSENSITIVE_ORDER(返回不区分大小写的Comparator)的区别,我们在'London'使用小写的'L'。

基本上,在Java 7中,我们使用的Collections.sort()方法接受一个List参数,最终返回一个Comparator,而在Java 8中新的List.sort()方法,它接受Comparator参数。

2.对整数列表进行排序

List<Integer> numbers = Arrays.asList(6, 2, 1, 4, 9);
System.out.println(numbers); //[6, 2, 1, 4, 9]
numbers.sort(Comparator.naturalOrder());
System.out.println(numbers); //[1, 2, 4, 6, 9]

3.按字符串字段对列表进行排序

假设我们有Movie类,想按标题对列表进行排序。我们可以使用Comparator.comparing()并传递用于排序的字段——在本例中为title。

List<Movie> movies = Arrays.asList(
    new Movie("Lord of the rings"),
    new Movie("Back to the future"),
    new Movie("Carlito's way"),
    new Movie("Pulp fiction"));
movies.sort(Comparator.comparing(Movie::getTitle));
movies.forEach(System.out::println);

输出是:

Movie{title='Back to the future'}
Movie{title="Carlito's way"}
Movie{title='Lord of the rings'}
Movie{title='Pulp fiction'}

你可能已经注意到,我们没有通过比较器(Comparator),但List已正确排序,这是因为提取的字段title是String类型,而String实现了Comparable接口。

如果你查看Comparator.comparison()的实现,你将看到它对提取的键调用compareTo方法。

return (Comparator<T> & Serializable)
    (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

4.按Double字段排序列表

以类似的方式,可以使用Comparator.comparingDouble()来比较double值。在示例中,我们希望通过评级从高到低来对电影列表进行排序。

List<Movie> movies = Arrays.asList(
    new Movie("Lord of the rings", 8.8),
    new Movie("Back to the future", 8.5),
    new Movie("Carlito's way", 7.9),
    new Movie("Pulp fiction", 8.9));
movies.sort(Comparator.comparingDouble(Movie::getRating)
           .reversed());
movies.forEach(System.out::println);

我们使用反转函数(reversed)来反转默认从低到高的自然排序,Comparator.comparingDouble() 底层使用Double.compare()实现。如果需要比较int或long,可以分别使用comparisonInt()comparisonLong()

5.使用自定义比较器对列表进行排序

在前面的例子中,没有指定任何Comparator,因为没有必要。现在让我们看一个自定义Comparator的例子。
我们的Movie类有一个新字段——'starred'。使用第三个构造函数设置参数。在示例中,我们要对列表进行排序,以便在列表顶部显示已加星标的电影。

List<Movie> movies = Arrays.asList(
    new Movie("Lord of the rings", 8.8, true),
    new Movie("Back to the future", 8.5, false),
    new Movie("Carlito's way", 7.9, true),
    new Movie("Pulp fiction", 8.9, false));
movies.sort(new Comparator<Movie>() {
  @Override
  public int compare(Movie m1, Movie m2) {
    if(m1.getStarred() == m2.getStarred()){
      return 0;
    }
    return m1.getStarred() ? -1 : 1;
   }
});
movies.forEach(System.out::println);

结果是:

Movie{starred=true, title='Lord of the rings', rating=8.8}
Movie{starred=true, title="Carlito's way", rating=7.9}
Movie{starred=false, title='Back to the future', rating=8.5}
Movie{starred=false, title='Pulp fiction', rating=8.9}

当然,我们可以使用lambda表达式而不是匿名类(Anonymous class),如下所示:

movies.sort((m1, m2) -> {
  if(m1.getStarred() == m2.getStarred()){
    return 0;
  }
  return m1.getStarred() ? -1 : 1;
});

也可以使用Comparator.comparing() :

movies.sort(Comparator.comparing(Movie::getStarred, (star1, star2) -> {
  if(star1 == star2){
     return 0;
  }
  return star1 ? -1 : 1;
}));

在后面的示例中,Comparator.comparing()接受用于排序的键作为第一个参数,并将Comparator作为第二个参数,该Comparator使用提取的键进行比较。star1和star2是布尔值,分别代表m1.getStarred()m2.getStarred()

6.使用比较器链对列表进行排序

最后一个示例中,我们希望将已加星标的电影放在顶部,然后按评分排序。

List<Movie> movies = Arrays.asList(
    new Movie("Lord of the rings", 8.8, true),
    new Movie("Back to the future", 8.5, false),
    new Movie("Carlito's way", 7.9, true),
    new Movie("Pulp fiction", 8.9, false));
movies.sort(Comparator.comparing(Movie::getStarred)
           .reversed()
           .thenComparing(Comparator.comparing(Movie::getRating)
           .reversed())
);
movies.forEach(System.out::println);

输出是:

Movie{starred=true, title='Lord of the rings', rating=8.8}
Movie{starred=true, title="Carlito's way", rating=7.9}
Movie{starred=false, title='Pulp fiction', rating=8.9}
Movie{starred=false, title='Back to the future', rating=8.5}

正如你所看到的,我们首先按是否加星标进行排序,然后按照评级进行排序——两者都进行了反转排序,因为我们想要评分高且标星的靠前。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Java函数式编程(九):Comparator

    实现Comparator接口 Comparator接口的身影在JDK库中随处可见,从查找到排序,再到反转操作,等等.Java 8里它变成了一个函数式接口,这样的好处就是我们可以使用流式语法来实现比较器了. 我们用几种不同的方式来实现一下Comparator,看看新式语法的价值所在.你的手指头会感谢你的,不用实现匿名内部类少敲了多少键盘啊. 使用Comparator进行排序 下面这个例子将使用不同的比较方法,来将一组人进行排序.我们先来创建一个Person的JavaBean. 复制代码 代码如下:

  • Java 中Comparable和Comparator区别比较

    Comparable 简介Comparable 是排序接口.若一个类实现了Comparable接口,就意味着"该类支持排序".  即然实现Comparable接口的类支持排序,假设现在存在"实现Comparable接口的类的对象的List列表(或数组)",则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序.此外,"实现Comparable接口的类的对象"可以用作"有序映射(如Tre

  • java中List对象列表实现去重或取出及排序的方法

    前言 因为在面试的时候碰到几次list的去重和排序,觉着有必要给大家总结一下具体的方法,分享出来供大家学习参考,话不多说了,来一起看看下面介绍的一种做法: 一.list去重 1.1 实体类Student List<Student>容量10k以上,要求去重复.这里Student的重复标准是属性相同,因此需要重写equals和hashcode方法,不知道有几个可以手写出来. student的equals方法: public void equals(Object o){ if(this == o)

  • Java中实现Comparator接口和用法实例(简明易懂)

    在java中,如果要对集合对象或数组对象进行排序,需要实现Comparator接口以达到我们想要的目标. 接下来我们模拟下在集合对象中对日期属性进行排序 一.实体类Step package com.ljq.entity; /** * 运号单流程 * * @author Administrator * */ public class Step{ /** 处理时间 */ private String acceptTime = ""; /** 快件所在地点 */ private String

  • java实现合并两个已经排序的列表实例代码

    相对于C++来说,Java的最大特点之一就是没有令人困惑的指针,但是我们不可否认,在某些特定的情境下,指针确实算的上一把利刃.虽然Java中没有明确定义出指针,但是由于类的思想,我们可以使用class来实现指针的操作.小二,上栗子-----合并两个已经排序的列表,输出合并后列表的头结点,且合并后的列表中的元素是有序的. 需要时刻铭记于心的:在Java中,列表的一个节点其实就是某个类实例化的一个对象. 示例代码如下: 复制代码 代码如下: package DecemberOf2013; class

  • java比较器comparator使用示例分享

    复制代码 代码如下: import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List; public class ComparatorTest implements Comparator<stuEntity> { /**     * @param args     */    public static void main(String[] arg

  • Java实现拖拽列表项的排序功能

    在一些允许用户自定义栏目顺序的app(如:凤凰新闻.网易云音乐等),我们可以方便地拖拽列表项来完成列表的重新排序,进而完成对栏目顺序的重排.这个功能很人性化,而实现起来其实很简单(甚至都不用写什么后台代码),只有三步. ①把冰箱门打开 首先,我们需要让冰箱的大门敞开,也就是允许我们进行拖拽的相关操作.以ListView为例,注意下面几个属性. <StackPanel> <ListView x:Name="list" AllowDrop="True"

  • 对比Java中的Comparable排序接口和Comparator比较器接口

    Comparable Comparable 是排序接口. 若一个类实现了Comparable接口,就意味着"该类支持排序". 即然实现Comparable接口的类支持排序,假设现在存在"实现Comparable接口的类的对象的List列表(或数组)",则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序. 此外,"实现Comparable接口的类的对象"可以用作"有序映射(如Tree

  • Java8 Comparator: 列表排序的深入讲解

    在本文中,我们将看到几个关于如何在Java 8中对List进行排序的示例. 1.按字母顺序排序字符串列表 List<String> cities = Arrays.asList( "Milan", "london", "San Francisco", "Tokyo", "New Delhi" ); System.out.println(cities); //[Milan, london, San

  • Java8 Comparator排序方法实例详解

    这篇文章主要介绍了Java8 Comparator排序方法实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java8 中 Comparator 接口提供了一些静态方法,可以方便于我们进行排序操作,下面通过例子讲解下如何使用 对整数列表排序(升序) List<Integer> list = Arrays.asList(1, 4, 2, 6, 2, 8); list.sort(Comparator.naturalOrder()); Sys

  • java中使用map排序的实例讲解

    对列表进行排序也是我们经常遇到的问题,这里缩小一下范围,使用map来对列表排序.相信大家都有过TreeMap排序的经历,不过Map.Entry能按值进行排序,在用法上略胜一筹.下面我们会对这两种map排序的方法分别进行介绍,着重讲解Map.Entry排序的方法. 1.Map.Entry方法 把Map.Entry放进list,再用Comparator对list进行排序 List list = new ArrayList(map.entrySet()); Collections.sort(list,

  • Python 列表排序方法reverse、sort、sorted详解

    python语言中的列表排序方法有三个:reverse反转/倒序排序.sort正序排序.sorted可以获取排序后的列表.在更高级列表排序中,后两中方法还可以加入条件参数进行排序. reverse()方法 将列表中元素反转排序,比如下面这样 >>> x = [1,5,2,3,4] >>> x.reverse() >>> x [4, 3, 2, 5, 1] reverse列表反转排序:是把原列表中的元素顺序从左至右的重新存放,而不会对列表中的参数进行排序

  • Python列表排序方法reverse、sort、sorted详解

    python语言中的列表排序方法有3个: reverse反转/倒序排序 sort正序排序 sorted可以获取排序后的列表 在更高级列表排序中,后两中方法还可以加入条件参数进行排序. reverse()方法 将列表中元素反转排序,比如下面这样 >>> x = [1,5,2,3,4] >>> x.reverse() >>> x [4, 3, 2, 5, 1] reverse列表反转排序:是把原列表中的元素顺序从左至右的重新存放,而不会对列表中的参数进行排

  • Python对列表排序的方法实例分析

    本文实例讲述了Python对列表排序的方法.分享给大家供大家参考.具体分析如下: 1.sort()函数 sort()函数使用固定的排序算法对列表排序.sort()函数对列表排序时改变了原来的列表,从而让其中的元素能按一定的顺序排列,而不是简单的返回一个已排序的列表副本. 注意sort()函数改变原来的列表,函数返回值是空值即None.因此,如果需要一个已排好序的列表副本,同时又要保留原有列表不变的时候,就不能直接简单的使用sort()函数.为了实现上述功能使用sort()的方法是:先获取列表X的

  • python实现忽略大小写对字符串列表排序的方法

    本文实例讲述了python实现忽略大小写对字符串列表排序的方法,是非常实用的技巧.分享给大家供大家参考.具体分析如下: 先来看看如下代码: string = ''' the stirng Has many line In THE fIle jb51 net ''' list_of_string = string.split() print list_of_string #将字符串分离开,放入列表中 print '*'*50 def case_insensitive_sort(liststring

  • 利用jQuery对无序列表排序的简单方法

    利用jQuery对无序列表排序的原理是:获取到无序列表中的所有列表项,并转成数组形式,使用JavaScript函数对其进行排序后再次输出.其中使用到的jQuery函数有ready().get().text().each().append()和JavaScript函数sort(). 1.jQuery函数介绍 (1)jQuery函数get()--获取匹配元素集合 该函数取得所有匹配元素的一种向后兼容的方式(不同于jQuery对象,实际上是元素数组).其语法形式如下: object.get() 注:如

  • MySQL 按指定字段自定义列表排序的实现

    问题描述 大家都知道, MySQL 中按某字段升序排列的 SQL 为 (以 id 为例,下同): SELECT * FROM `MyTable` WHERE `id` IN (1, 7, 3, 5) ORDER BY `id` ASC 降序排列的 SQL 为: SELECT * FROM `MyTable` WHERE `id` IN (1, 7, 3, 5) ORDER BY `id` DESC 有时以上排序并不能满足我们的需求. 例如, 我们想要按 id 以 5, 3, 7, 1 的顺序排列

  • Python cookbook(数据结构与算法)通过公共键对字典列表排序算法示例

    本文实例讲述了Python通过公共键对字典列表排序算法.分享给大家供大家参考,具体如下: 问题:想根据一个或多个字典中的值来对列表排序 解决方案:利用operator模块中的itemgetter()函数对这类结构进行排序是非常简单的. # Sort a list of a dicts on a common key rows = [ {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Be

随机推荐