Java Comparator接口实例讲解(抽象方法、常用静态/默认方法)
时间:2018-08-25
本文章向大家介绍Java Comparator接口实例讲解(抽象方法、常用静态/默认方法),需要的朋友可以参考一下
Comparator
是一个泛型函数式接口,T
表示待比较对象的类型:
@FunctionalInterface
public interface Comparator<T> {
}
1. 抽象方法
唯一的非Object抽象方法: compare
int compare(T o1, T o2)
根据o1, o2的大小关系返回:负数、0、正数
其比较逻辑依赖于赋值给Comparator
类型变量的Lambda表达式、Comparator
对象等:
Comparator<String> comparator = Comparator.comparingInt(String::length); // 比较String类对象的length
System.out.println(comparator.compare("Tom", "Jerry")); // -1
2. 常用静态/默认方法
① 静态方法comparing
// 源码1
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));
}
-
返回值:
comparing
返回一个T
类型的Comparator
对象(也就是用于比较T
类型对象的Comparator
) -
参数:
comparing
的参数是一个Function
类型,它接收T
类型及T
的超类型, 返回U
类型及U
的子类型。keyExtractor
用Lambda表达式实现例如,输入
String
,提取其长度:Comparator<String> keyComparator = Comparator.comparing(String::length); keyComparator.compare("Tom", "Jerry");
- 函数体:
- 首先,确保
keyExtractor
不是null
- 然后,返回一个Lambda表达式,该表达式对
c1
和c2
提取出来的key
进行比较 (用的是c1
和c2
类实现的compareTo()
进行比较)
- 首先,确保
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));
}
与上面类似,只不过将key
的比较逻辑由compareTo()
替换成了自定义的比较逻辑
实例:
package Lambda.ComparatorDemo;
import java.util.Arrays;
import java.util.Comparator;
class Person {
private String fname;
private String lname;
public Person(String fname, String lname) {
this.fname = fname;
this.lname = lname;
}
public String getFname() {
return fname;
}
public String getLname() {
return lname;
}
@Override
public String toString() {
return fname + " " + lname;
}
}
public class ComparingDemo {
public static void main(String[] args) {
Person p1 = new Person("Tom", "Kenn");
Person p2 = new Person("Alice", "Zed");
Person[] persons1 = {p1, p2};
Person[] persons2 = persons1.clone();
// 依据First Name排序(用的是String类的compareTo的比较逻辑)
Arrays.sort(persons1, Comparator.comparing(Person::getFname));
System.out.println("Person1 (Sorted by first name): ");
for (Person p : persons1) {
System.out.println(p);
}
System.out.println();
// 依据First Name的长度排序
Arrays.sort(persons2, Comparator.comparing(Person::getFname, Comparator.comparingInt(String::length)));
System.out.println("Person2 (Sorted by length of first name):");
for (Person p : persons2) {
System.out.println(p);
}
}
}
② 静态方法comparingXXX()
comparingInt()
comparingDouble()
comparingLong()
与comparing
是一样的思路,只不过comparingXXX()
将comparing
中的提取出来的key
类型固定为了XXX
:
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
③ 默认方法thenComparing()
thenComparing
是默认方法,需要对具体的Comparator
对象调用,它用于将多个Comparator
结合起来实现“链式的比较”:先根据XXX比较,再根据XXX比较,...
// 源码
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
public class thenComparingDemo {
public static void main(String[] args) {
Person p1 = new Person("Alice", "Jessy");
Person p2 = new Person("Alice", "Ann");
Person p3 = new Person("Tom", "Smith");
Person[] persons = {p1, p2, p3};
// 先根据first name比较,再根据last name的长度比较
Comparator<Person> chainedComparator = Comparator.comparing(Person::getFname)
.thenComparing((x, y) -> (x.getLname().length() - y.getLname().length()));
// 先根据first name排序,再根据last name的长度排序
Arrays.sort(persons, chainedComparator);
for (Person p : persons) {
System.out.println(p);
}
}
}
/*
Alice Ann
Alice Jessy
Tom Smith
参考:
https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#thenComparing-java.util.Comparator
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- DB2备份还原相关操作
- MySQL复制全解析 Part 8 MySQL Auto-Positioning
- Redis 5.0.8 主从搭建
- Linux 修改网卡名称及mac地址
- MySQL Galera Cluster全解析 Part 10 grastate.dat文件详解
- MySQL MHA部署 Part 7 MHA手动切换测试
- 使用sysbench进行压测 Part2 sysbench语法介绍
- mysqlbinlog命令详解 Part 1-实验环境准备
- mysqlbinlog命令详解 Part 2 -MySQL 事件类型
- mysqlbinlog命令详解 Part 4 -查看行事件具体SQL语句
- mysqlbinlog命令详解 Part 5 通过位置和时间查看日志
- mysqlbinlog命令详解 Part 6 读取远程MySQL服务器日志
- mysqlbinlog命令详解 Part 7 备份二进制日志文件
- mysqlbinlog命令详解 Part 8 指定 Server ID
- mysqlbinlog命令详解 Part 9 MySQL备份策略