Java 8 比较器:如何对 List 排序
在本文中,我们将看到几个关于如何在Java 8中对List进行排序的例子。
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]
London的“L”使用小写字母,是为了更好地突出 Comparator.naturalOrder() (返回首先排序大写字母的比较器)和 String.CASE_INSENSITIVE_ORDER(返回不区分大小写的比较器)之间的差异。
基本上,在Java 7中,我们使用Collection.sort()接受List和最后的Comparator ——在Java 8中,我们有新的 List.sort() 用于接受Comparator。
对整数列表排序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]按字符串字段对列表排序
假设我们有一个Movie类,并且我们要“按标题title”对List排序。我们可以使用 Comparator.comparing() ,传递一个函数,函数提取用于排序title的字段——在本例中。
List Movie movies = Arrays.asList( new Movie("Lord of the rings"), new Movie("Back to the future"), new Movie("Carlitos way"), new Movie("Pulp fiction")); movies.sort(Comparator.comparing(Movie::getTitle)); movies.forEach(System.out::println);
输出:
Movie{title=Back to the future} Movie{title=Carlitos way} Movie{title=Lord of the rings} Movie{title=Pulp fiction}
可能你会注意到我们没有通过任何Comparator ,但正确排序了List。这是因为title——提取的字段——是一个字符串,并且字符串实现了可比较的接口。如果你看看Comparator.comparing()实现,你会看到它对提取的键调用compareTo。
return (Comparator T Serializable) (c1, c2) - keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));按double字段对列表排序
以类似的方式,我们可以使用 Comparator.comparingDouble()来比较double值。在示例中,我们想按最高到最低的评分来订购Movie列表。
List Movie movies = Arrays.asList( new Movie("Lord of the rings", 8.8), new Movie("Back to the future", 8.5), new Movie("Carlitos way", 7.9), new Movie("Pulp fiction", 8.9)); movies.sort(Comparator.comparingDouble(Movie::getRating) .reversed()); movies.forEach(System.out::println);
我们在Comparator上使用reversed函数,以便反转默认的从最低到最高的自然顺序。 Comparator.comparingDouble()在内部使用Double.compare()。
如果你需要比较int或long,那么你可以分别使用comparingInt()和comparingLong()。
使用自定义比较器对列表排序在前面的例子中,我们没有指定任何比较器,因为没有必要,但让我们看一个例子,例子中我们定义了我们自己的比较器。我们的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("Carlitos 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=Carlitos 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类,如下所示:
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()。
用比较链排序列表在最后一个例子中,我们要在顶部加上已加星标的电影,然后按评分排序。
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("Carlitos 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=Carlitos way, rating=7.9} Movie{starred=false, title=Pulp fiction, rating=8.9} Movie{starred=false, title=Back to the future, rating=8.5}
正如你所看到的,我们首先按星标,然后按评分进行排序——两者都反转,因为我们想要最高的值和真正的第一。
作者:小峰
来源:51CTO
【Java】七大排序(详解 + 代码 + 变种) 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。平时的上下文中,如果提到排序,通常指的是排升序(非降序)。
相关文章
- 总是记不住java的IO流用法?用N个问题教你掌握java IO流
- MessagePack Java 0.6.X List, Map 对象的序列化和反序列化
- Java中 List、Set、Map遍历方式以及性能比较
- Java中 List、Set、Map 之间的区别
- Java--如何高效向List中存放不重复的数据(附带时间测试)
- Java List集合冒泡法排序的两种实现
- java中yield 和join的作用
- Java码农必须掌握的循环删除List元素的正确方法!
- 区块链编程七大语言,使用最多的竟是Java(1),Java岗面试
- JAVA多线程经典范列:生产者与消费者
- AndroidStudio离线打包MUI集成JPush极光推送并在java后端管理推送
- Java开发笔记之List删除元素foreach删除元素
- [Java]枚举类型:遍历为List
- 零基础的人怎么学习Java
- LeetCode109_Convert Sorted List to Binary Search t题目tiTree(将链表转成二叉排序树) Java题解
- java 反射获取字段为List类型中的泛型类型
- Java 基础——List 与数组、Map 相互转换
- Java 做项目能用到 List 的场景,这篇总结全了
- java List转变为逗号分隔的字符串(字符串去重)
- 【已解决】Android Studio 加载自定义properties文件出错java.lang.ExceptionInInitializerError Caused by: java.lang.Nu
- java 集合(list、set、map)的特点
- Java中如何优雅地删除List中的元素
- 我的Android进阶之旅------>对Java中注释/**@hide*/的初步认识