Comparator.comparing比较排序
使用外部比较器Comparator进行排序
当我们需要对集合的元素进行排序的时候,可以使用java.util.Comparator 创建一个比较器来进行排序。Comparator接口同样也是一个函数式接口,我们可以把使用lambda表达式。如下示例,
package com.common;
import java.util.*;
import java.util.stream.Collectors;
public class ComparatorTest {
public static void main(String[] args) {
Employee e1 = new Employee("John", 25, 3000, 9922001);
Employee e2 = new Employee("Ace", 22, 2000, 5924001);
Employee e3 = new Employee("Keith", 35, 4000, 3924401);
List<Employee> employees = new ArrayList<>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
/**
* @SuppressWarnings({"unchecked", "rawtypes"})
* default void sort(Comparator<? super E> c) {
* Object[] a = this.toArray();
* Arrays.sort(a, (Comparator) c);
* ListIterator<E> i = this.listIterator();
* for (Object e : a) {
* i.next();
* i.set((E) e);
* }
* }
*
* sort 对象接收一个 Comparator 函数式接口,可以传入一个lambda表达式
*/
employees.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
Collections.sort(employees, (o1, o2) -> o1.getName().compareTo(o2.getName()));
employees.forEach(System.out::println);
}
}
/**
* [Employee(name=John, age=25, salary=3000.0, mobile=9922001),
* Employee(name=Ace, age=22, salary=2000.0, mobile=5924001),
* Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]
*/
class Employee {
String name;
int age;
double salary;
long mobile;
// constructors, getters & setters
public Employee(String name, int age, double salary, long mobile) {
this.name = name;
this.age = age;
this.salary = salary;
this.mobile = mobile;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public long getMobile() {
return mobile;
}
public void setMobile(long mobile) {
this.mobile = mobile;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Employee{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", salary=").append(salary);
sb.append(", mobile=").append(mobile);
sb.append('}');
return sb.toString();
}
}
使用 Comparator.comparing 进行排序
comparing 方法一
查看 Comparator 类内部实现,还有一个 comparing 方法,实现如下,
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
其返回值是 (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); 一个lambda表达式,也就是一个Compator 。所以上面那个例子也可以改造成 如下,
package com.common;
import java.util.*;
public class ComparatorTest {
public static void main(String[] args) {
Employee e1 = new Employee("John", 25, 3000, 9922001);
Employee e2 = new Employee("Ace", 22, 2000, 5924001);
Employee e3 = new Employee("Keith", 35, 4000, 3924401);
List<Employee> employees = new ArrayList<>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
/**
* @SuppressWarnings({"unchecked", "rawtypes"})
* default void sort(Comparator<? super E> c) {
* Object[] a = this.toArray();
* Arrays.sort(a, (Comparator) c);
* ListIterator<E> i = this.listIterator();
* for (Object e : a) {
* i.next();
* i.set((E) e);
* }
* }
*
* sort 对象接收一个 Comparator 函数式接口,可以传入一个lambda表达式
*/
employees.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
Collections.sort(employees, (o1, o2) -> o1.getName().compareTo(o2.getName()));
employees.forEach(System.out::println);
/**
* Comparator.comparing 方法的使用
*
* comparing 方法接收一个 Function 函数式接口 ,通过一个 lambda 表达式传入
*
*/
employees.sort(Comparator.comparing(e -> e.getName()));
/**
* 该方法引用 Employee::getName 可以代替 lambda表达式
*/
employees.sort(Comparator.comparing(Employee::getName));
}
}
/**
* [Employee(name=John, age=25, salary=3000.0, mobile=9922001),
* Employee(name=Ace, age=22, salary=2000.0, mobile=5924001),
* Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]
*/
class Employee {
String name;
int age;
double salary;
long mobile;
// constructors, getters & setters
public Employee(String name, int age, double salary, long mobile) {
this.name = name;
this.age = age;
this.salary = salary;
this.mobile = mobile;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public long getMobile() {
return mobile;
}
public void setMobile(long mobile) {
this.mobile = mobile;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Employee{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", salary=").append(salary);
sb.append(", mobile=").append(mobile);
sb.append('}');
return sb.toString();
}
}
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));
}
和comparing 方法一不同的是 该方法多了一个参数 keyComparator ,keyComparator 是创建一个自定义的比较器。
Collections.sort(employees, Comparator.comparing(
Employee::getName, (s1, s2) -> {
return s2.compareTo(s1);
}));
使用 Comparator.reversed 进行排序
返回相反的排序规则,
/**
* 相反的排序规则
*/
Collections.sort(employees, Comparator.comparing(Employee::getName).reversed());
employees.forEach(System.out::println);
输出,
Employee{name='Keith', age=35, salary=4000.0, mobile=3924401}
Employee{name='John', age=25, salary=3000.0, mobile=9922001}
Employee{name='Ace', age=22, salary=2000.0, mobile=5924001}
使用 Comparator.nullsFirst进行排序
当集合中存在null元素时,可以使用针对null友好的比较器,null元素排在集合的最前面
employees.add(null); //插入一个null元素
Collections.sort(employees, Comparator.nullsFirst(Comparator.comparing(Employee::getName)));
employees.forEach(System.out::println);
Collections.sort(employees, Comparator.nullsLast(Comparator.comparing(Employee::getName)));
employees.forEach(System.out::println);
使用 Comparator.thenComparing排序
首先使用 name 排序,紧接着在使用ege 排序,来看下使用效果
Collections.sort(employees, Comparator.comparing(Employee::getAge).thenComparing(Employee::getName));
employees.forEach(System.out::println);
转载:https://my.oschina.net/xinxingegeya/blog/2046405
Comparator.comparing比较排序的更多相关文章
- Comparator.comparing排序使用示例
Comparator.comparing排序使用示例 目录 Comparator.comparing排序使用示例 背景 实体类 示例一 示例二 背景 以前常用的排序方式是通过实现Comparator接 ...
- [转] Java中Comparator进行对象排序
[From] https://blog.51cto.com/thinklili/2063244 Java在8后引入了lambda表达式和流,使得排序方法有了变化 class User { int id ...
- Java基础 TreeSet()来实现数组的【定制排序】 : Comparable接口(自然排序) 或者 Comparator接口 (定制排序)
笔记: //排序真麻烦!没有C++里的好用又方便!ORZ!ORZ!数组排序还还自己写个TreeSet()和( Comparable接口(自然排序) 或者 Comparator接口 (定制排序))imp ...
- java运用Comparator为对象排序
要排序的类需要实现Comparator接口,重写compare方法: user类及实现接口的内部类: package test; import java.util.Comparator; public ...
- Comparator接口实现排序
对任意类型集合对象进行整体排序,排序时将此接口的实现传递给Collections.sort方法或者Arrays.sort方法排序.实现int compare(T o1, T o2);方法,返回正数,零 ...
- TreeSet和Comparator 对TreeSet排序
使用TreeSet和Comparator,编写TreeSetTestInner类,要求对TreeSet中的元素"HashSet"."ArrayList".&qu ...
- TreeSet实现Comparator接口的排序算法的分析
为了方便,用lambda表达式代替comparator接口 例子如下: public static void main(String[] args) { TreeSet<Integer> ...
- Java中List排序的3种方法
在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作.比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进 ...
- Java8:使用Lambda表达式增强版Comparator排序
学习路上的自我记录-------路好长,就问你慌不慌,大声港,不慌.----jstarseven. 实体类: package com.server.model; /** * Created by js ...
随机推荐
- 【转】IntelliJ IDEA搭建Spring环境
//本来在草稿箱写好了,忘记发就被冲掉了,重新再写一遍. Spring初探 Spring初探 在IntelliJ IDEA中创建Spring项目 一个简单的例子介绍框架的作用 那么什么时候new的对象 ...
- 【旧文章搬运】分析了一下360安全卫士的HOOK
原文发表于百度空间及看雪论坛,2009-10-08 看雪论坛地址:https://bbs.pediy.com/thread-99128.htm 看时间,09年的国庆节基本上就搞这玩意儿了...==== ...
- 整体二分 HDU - 5808
题目大意 有n个物品,排成一个序列,每个物品有一个di表示取到i要走的距离,vi表示i的价值. 给m组询问[l,r] ,c,sum,问由[l,r]的di<=c的物品能否凑出sum的价值(每个物品 ...
- UVaLive 6585 && Gym 100299F Draughts (暴力+回溯)
题意:给定一个 10*10的矩阵,每一个W可以跳过一个B向对角走到#并把B吃掉,并且可以一直跳直到不能动为止,现在是W走的时候,问你最多吃几个B. 析:直接暴力+回溯,深搜就好. 代码如下: #pra ...
- GCC在C语言中内嵌汇编 asm __volatile__
2012-11-26 22:20 17958人阅读 评论(2) 收藏 举报 分类: linux(59) 架构管理(24) C/C++(59) 目录(?)[+] 在内嵌汇编中,可以将C语言表达式 ...
- AtCoder Regular Contest 061 DSnuke's Coloring
http://arc061.contest.atcoder.jp/tasks/arc061_b 题意: H行W列的矩阵中,然后挖了n个洞,输出j(0-9)行,对于第i行输出,有多少个3*3区域中有i个 ...
- c# 组件无法下断点
1. c#组件 2.断点能下,且运行中断点本身显示正常(正常实心红点,不是白底红圈) 3.运行中无法进入组件 4.主程序中,组件的实例无法被观测到,调试显示:无法计算得到这个对象 , 但是程序能运行 ...
- jdbc 连接 sqlserver 学习
使用sqljdbc.jar 连接sqlserver 下载网址: http://www.drv5.cn/sfinfo/8228.html#softdown package test_sql_server ...
- 温习LOGO语言
LOGO是什么? LOGO语言是一种早期的编程语言,也是一种与自然语言非常接近的编程语言,它通过"绘图"的方式来学习编程,对初学者特别是儿童进行寓教于乐的教学方式. LOGO语言创 ...
- Window下完全卸载删除Nodejs
如何从Windows中删除Node.js: 1.从卸载程序卸载程序和功能. 2.重新启动(或者您可能会从任务管理器中杀死所有与节点相关的进程). 3.寻找这些文件夹并删除它们(及其内容)(如果还有). ...