使用外部比较器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比较排序的更多相关文章

  1. Comparator.comparing排序使用示例

    Comparator.comparing排序使用示例 目录 Comparator.comparing排序使用示例 背景 实体类 示例一 示例二 背景 以前常用的排序方式是通过实现Comparator接 ...

  2. [转] Java中Comparator进行对象排序

    [From] https://blog.51cto.com/thinklili/2063244 Java在8后引入了lambda表达式和流,使得排序方法有了变化 class User { int id ...

  3. Java基础 TreeSet()来实现数组的【定制排序】 : Comparable接口(自然排序) 或者 Comparator接口 (定制排序)

    笔记: //排序真麻烦!没有C++里的好用又方便!ORZ!ORZ!数组排序还还自己写个TreeSet()和( Comparable接口(自然排序) 或者 Comparator接口 (定制排序))imp ...

  4. java运用Comparator为对象排序

    要排序的类需要实现Comparator接口,重写compare方法: user类及实现接口的内部类: package test; import java.util.Comparator; public ...

  5. Comparator接口实现排序

    对任意类型集合对象进行整体排序,排序时将此接口的实现传递给Collections.sort方法或者Arrays.sort方法排序.实现int compare(T o1, T o2);方法,返回正数,零 ...

  6. TreeSet和Comparator 对TreeSet排序

    使用TreeSet和Comparator,编写TreeSetTestInner类,要求对TreeSet中的元素"HashSet"."ArrayList".&qu ...

  7. TreeSet实现Comparator接口的排序算法的分析

    为了方便,用lambda表达式代替comparator接口 例子如下: public static void main(String[] args) { TreeSet<Integer> ...

  8. Java中List排序的3种方法

    在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作.比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进 ...

  9. Java8:使用Lambda表达式增强版Comparator排序

    学习路上的自我记录-------路好长,就问你慌不慌,大声港,不慌.----jstarseven. 实体类: package com.server.model; /** * Created by js ...

随机推荐

  1. flask中manage.py的用法

    flask中manage.py的用法#!/usr/bin/env pythonimport osfrom app import create_app, dbfrom app.models import ...

  2. http基础知识摘录

    HTTP是一个基于请求/响应模式的,无状态的协议 (只有客户端发送请求服务器才会响应,否则服务器不会主动发送信息的,无状态指客户端发过来一个请求服务端给你发回一个响应,接着你再去发送一个请求,服务器根 ...

  3. node安装升级npm

    安装npm npm上有很多优秀的nodejs包,来解决常见的一些问题,比如用node-mysql,就可以方便通过nodejs链接到mysql,进行数据库的操作 在开发过程往往会需要用到其他的包,使用n ...

  4. nodejs QueryString模块 详解

    QueryString模块 "QueryString" 模块用于实现URL参数字符串与参数对象的互相转换 此类一共包括4个方法: querystring.stringify(obj ...

  5. 1004 n^n的末位数字

    题目来源: Author Ignatius.L (Hdu 1061) 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题   给出一个整数N,输出N^N(N的N次方)的十 ...

  6. Playground Tutorial

    In this step by step tutorial we'll walk through setting up a business network, defining our assets, ...

  7. Androidstudio中添加jar包的方法

    在Androidstudio中添加一个jar包进去,怎么添加? 以下纯个人使用Androidstudio过程中的经验积累,要是有不足,望提出建议. 方法一: 先点击Androidstudio中的Pro ...

  8. hdu 3622 Bomb Game【二分+2-SAT+tarjan】

    用read()会挂 二分半径,显然最优的是所有原都用这个最小半径,然后2-SAT把相交的圆建图,跑tarjan判一下可行性即可 #include<iostream> #include< ...

  9. 第十八篇 .NET高级技术之Linq与EF Code-First Fluent API基础讲解

    1.FluentApi简介 在这里提供了一个fluentapi基础的DEMO然后咱们在进一步的学习,直接上干货. 第一步在数据库创建一个表:person 第二步:新建控制台程序FluentAPI 第三 ...

  10. 第十二篇 .NET高级技术之lambda表达式

    最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...