Java 8 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}
正如你所看到的,我们首先按是否加星标进行排序,然后按照评级进行排序——两者都进行了反转排序,因为我们想要评分高且标星的靠前。
欢迎关注公众号:锅外的大佬 (良心公众号) 每日推送来自国外的翻译文章,帮助每位国内的技术人
原文链接:https://dzone.com/articles/java-8-comparator-how-to-sort-a-list
作者: Mario Pio Gioiosa https://dzone.com/users/1354529/mariocidio.html
译者:Steephan
Java 8 Comparator: 列表排序的更多相关文章
- Java list对象列表排序 实例
package com.test; public class Bean { private String name; private int priority; public String getNa ...
- [Java] 用 Comparator 实现排序
最近正好用到Comparator,发现能对不同类型的对象进行排序(当然排序依据还是基本类型),也不用自己实现排序算法,用起来很方便,所以简单记录一下. 本文地址:http://www.cnblogs. ...
- 我的Java开发学习之旅------>Java利用Comparator接口对多个排序条件进行处理
一需求 二实现Comparator接口 三验证排序结果 验证第一条件首先按级别排序级别最高的排在前面 验证第二条如果级别相等那么按工资排序工资高的排在前面 验证第三条如果工资相当则按入职年数排序入职时 ...
- Java - 简单的对象排序 - Comparator
注:对象排序,就是对对象中的某一字段进行比较,以正序或倒序进行排序. 例: 需要排序的对象: public class Person { public int age; public String n ...
- Java 中Comparator 的使用,实现集合排序
目标:实现对Person 对象的年龄,从小到大排序 1.实现排序 package com.app; import java.util.ArrayList; import java.util.Colle ...
- java运用Comparator为对象排序
要排序的类需要实现Comparator接口,重写compare方法: user类及实现接口的内部类: package test; import java.util.Comparator; public ...
- [Java] 使用Comparator排序对象
package test.collections; import java.util.ArrayList; import java.util.Collection; import java.util. ...
- 【java】实现Interface java.lang.Comparable<T>接口的int compareTo(T o)方法实现对象数组或链表或集合的排序,和挽救式对象比较器Interface java.util.Comparator<T>
package 对象比较排序; import java.util.Arrays; class A implements Comparable<A>{ private String name ...
- JAVA之旅(二十)—HashSet,自定义存储对象,TreeSet,二叉树,实现Comparator方式排序,TreeSet小练习
JAVA之旅(二十)-HashSet,自定义存储对象,TreeSet,二叉树,实现Comparator方式排序,TreeSet小练习 我们继续说一下集合框架 Set:元素是无序(存入和取出的顺序不一定 ...
随机推荐
- 【高精度】模板 (C++)
//n为长度 1.高精加 复杂度:O(n) #include<iostream> #include<cstring> #include<algorithm> usi ...
- [GDOI2016][树链剖分+主席树]疯狂动物城
题面 Description Nick 是只在动物城以坑蒙拐骗为生的狐狸,儿时受到偏见的伤害,放弃了自己的理想.他被兔子 Judy 设下圈套,被迫与她合作查案,而卷入意想不到的阴谋,历尽艰险后成为搭档 ...
- Linux下 导入导出数据库
1.怎么找到mysql下的bin? 1.1首先我在网上百度了一些Linux下如何导入导出数据.基本都是用mysqldump命令,但是如果没有到指定目录 下,执行这个命令是没有用的.一开始我还以为要在m ...
- Kali 安装VMtools(最新)
老方法安装的VMtools不能进行主宿切换,下面是kali最新版安装VMtools的方法 一.换国内源&更新源 参考 Kali 2017更新源 二.安装VMtools apt-get inst ...
- 4 Template层 -模板继承
1.模板继承 模板继承可以减少页面内容的重复定义,实现页面内容的重用 典型应用:网站的头部.尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义 block标签:在父模板中预留区域,在子模板 ...
- 驱动模块 .ko
模块: 模块机制,作用搞高LINUX操作系统的扩充性. 1. 模块概念: 1.动态可加载内核模块LKM 2.内核空间运行 3.是不是一执行文件,是一个没有经过链接,不能独立运行的一个目标文件(.c-& ...
- C语言编程题001
有一颗树,一年两个生长周期,春天它长高一倍,夏天长高1m,问N个周期后树有多高?假设从春天开始树高为1m,第0个周期树高为1m. 要求:1.可以同时输入多个生长周期 如:3//表示下面有几个生长周期 ...
- [19/02/23]ToolsShare 工具分享 VPNTethering Android (Root Required)
To be short, VPN Tethering is a quite useful tool when you want to share your private network with s ...
- (转)iOS-蓝牙学习资源博文收集
ios蓝牙开发(一)蓝牙相关基础知识 ios蓝牙开发(二)蓝牙中心模式的ios代码实现 ios蓝牙开发(三)app作为外设被连接的实现 ios蓝牙开发(四)BabyBluetooth蓝牙库介绍 暂未完 ...
- border-radius元素overflow:hidden失效问题
父元素使用border-radius和overflow:hidden做成圆形,子元素如果使用了transform属性,则父元素的overflow:hidden会失效. 解决方法: 父元素使用 -wei ...