使用外部比较器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. unittest参数化parameterized

    参考文章: https://www.cnblogs.com/royfans/p/7226360.html https://blog.csdn.net/zha6476003/article/detail ...

  2. A. Hulk

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...

  3. k8s-资源指标API及自定义指标API-二十三

    一. 原先版本是用heapster来收集资源指标才能看,但是现在heapster要废弃了. 从k8s v1.8开始后,引入了新的功能,即把资源指标引入api: 在使用heapster时,获取资源指标是 ...

  4. js跳转方法整理与自动刷新

    js方式的页面跳转1.window.location.href方式 <script language="JavaScript" type="text/javascr ...

  5. Codeforces - 702A - Maximum Increase - 简单dp

    DP的学习计划,刷 https://codeforces.com/problemset?order=BY_RATING_ASC&tags=dp 遇到了这道题 https://codeforce ...

  6. 洛谷 - P1004 - 方格取数 - 简单dp

    https://www.luogu.org/problemnew/show/P1004 这道题分类到简单dp但是感觉一点都不简单……这种做两次的dp真的不是很懂怎么写.假如是贪心做两次,感觉又不能证明 ...

  7. 基础BFS+DFS poj3083

    //满基础的一道题 //最短路径肯定是BFS. //然后靠右,靠左,就DFS啦 //根据前一个状态推出下一个状态,举靠左的例子,如果一开始是上的话,那么他的接下来依次就是 左,上 , 右 , 下 // ...

  8. 纯拓扑排序一搞poj2367

    /* author: keyboarder time : 2016-05-18 12:21:26 */ #include<cstdio> #include<string.h> ...

  9. bzoj 2565: 最长双回文串【manacher+线段树】

    因为我很愚蠢所以用了很愚蠢的O(nlogn)的manacher+线段树做法 就是开两个线段树mn和mx分别表示左端点在i的最长回文子串和右端点在i的最长回文子串 用manacher求出每个点的最长回文 ...

  10. Django学习:模板语法

    一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法分类 一.模板语法之变量:语法为 {{ }}: 在 Django 模板中遍历复杂数据结构的关键 ...