Comparable 与 Comparator 比较
项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步
1.两个接口的原型
Java中,Comparable与Comparator接口都是用来做比较的。那么这两个接口在实际使用中到底有什么不同呢?下面我们来结合实例分析一下。
先看看两个接口在JDK中的原型。
package java.lang;
import java.util.*;public interface Comparable<T> {public int compareTo(T o);
}
package java.util;import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;@FunctionalInterface
public interface Comparator<T> {int compare(T o1, T o2);boolean equals(Object obj);
}
2.Comparable的用法
一般来说,Comparable是为了对某个类的集合进行排序,所以此时一般都是这个需要排序的类本身去实现Comparable接口。换句话说,如果某个类实现了Comparable接口,那么这个类的数组或者说List就可以进行排序了。
举个简单的例子:
public class Employee implements Comparable<Employee> {private String name;private int salary;public Employee(String name, int salary) {this.name = name;this.salary = salary;}@Overridepublic int compareTo(Employee other) {return this.salary - other.salary;}@Overridepublic String toString() {return "name is: " + name + ", salary is: " + salary;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}
}
在客户端中实现Employee集合排序:
public class CompareTest {public static List<Employee> genList() {Employee e1 = new Employee("aaa",100);Employee e2 = new Employee("bbb",150);Employee e3 = new Employee("ccc", 80);List<Employee> list = new ArrayList();list.add(e1);list.add(e2);list.add(e3);return list;}public static void t1() {List<Employee> list = genList();//Collections.sort(list); 两种方式都可以,此种方式源码中就是调用的list.sort(null)list.sort(null);System.out.println(list);}public static void main(String[] args) {t1();}}
将客户端的代码run起来,最后输出的结果为:
[name is: ccc, salary is: 80, name is: aaa, salary is: 100, name is: bbb, salary is: 150]
因为Employee实现了Comparable接口,所以能直接对Employee数组进行排序。
3.Comparator接口用法
很多时候我们无法对类进行修改,或者说此类修改的成本太高,但是又希望对其进行排序。那怎么办?这个时候Comparator接口就排上了用场。
比如我们将前面的Employee类稍作修改,不实现Comparable接口,加上final关键字:
public final class Employee {private String name;private int salary;public Employee(String name, int salary) {this.name = name;this.salary = salary;}@Overridepublic String toString() {return "name is: " + name + ", salary is: " + salary;}...此处省略get/set
}
这个时候我们显然无法修改Employee类了。但是还是需要对其排序,怎么办?
如果在jdk8之前,使用匿名内部类的方式:
public static void test() {List<Employee> list = genList();Collections.sort(list, new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {return o1.getSalary() - o2.getSalary();}});System.out.println(list);}
在jdk8之后,可以使用lambda表达式:
public static void test() {List<Employee> list = genList();Comparator<Employee> comparator = (Employee e1, Employee e2) -> e1.getSalary() - e2.getSalary();list.sort(comparator);System.out.println(list);}
如果将此方法run起来,输出如下:
[name is: ccc, salary is: 80, name is: aaa, salary is: 100, name is: bbb, salary is: 150]
同学们可能会注意到,Comparable接口中只有一个compareTo方法要实现,而Comparator有两个方法,但是我们只实现了一个方法,那么另外一个方法呢?
其实很简单,因为另外一个方法是equals方法。所有的类都继承了Object类,而Object类中实现了equals方法,所以我们这里不实现equals方法也无所谓!
4.Comparator中的各种实现方式比较
Comparator中的compare方法实现方式还是比较多的。下面我们来一一说明。
4.1 传统的匿名内部类
JDK8之前,一般是采用匿名内部类的方式实现:
Collections.sort(list, new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {return o1.getSalary() - o2.getSalary();}});
4.2 lambda表达式
JDK8之后,可以使用lambda表达式:
list.sort((Employee e1, Employee e2) -> e1.getSalary() - e2.getSalary());
4.3 精简版的lambda表达式
我们通过不指定类型定义来进一步简化表达式,因为编译器自己可以进行类型判断
list.sort((e1, e2) -> e1.getSalary() - e2.getSalary());
4.4 使用Comparator.comparing的方式
我们使用上述lambda表达式的时候,IDE会提示我们:can be replaced with comparator.comparing Int
list.sort(Comparator.comparing(employee -> employee.getSalary()));
4.5 使用静态方法的引用
java中的双冒号就是方法引用。::是JDK8里引入lambda后的一种用法,表示引用,比如静态方法的引用String::valueOf,比如构造器的引用,ArrayList::new。
list.sort(Comparator.comparing(Employee::getSalary));
4.6 排序反转
很多时候,想对排序进行反转,或者说逆序:
list.sort(Comparator.comparing(Employee::getSalary).reversed());
4.7 许多条件组合排序
list.sort((e1, e2) -> {if(e1.getSalary() != e2.getSalary()) {return e1.getSalary() - e2.getSalary();} else {return e1.getName().compareTo(e2.getName());}});
4.8 从JDK 8开始,我们现在可以把多个Comparator链在一起(chain together)去建造更复杂的比较逻辑
list.sort(Comparator.comparing(Employee::getSalary).thenComparing(Employee::getName));
Comparable 与 Comparator 比较相关推荐
- Java 中 Comparable 和 Comparator 比较
为什么80%的码农都做不了架构师?>>> 本文,先介绍Comparable 和Comparator两个接口,以及它们的差异:接着,通过示例,对它们的使用方法进行说明. Comp ...
- Java 解惑:Comparable 和 Comparator 的区别
读完本文你将了解到: Comparable 自然排序 Comparator 定制排序 总结 Java 中为我们提供了两种比较机制:Comparable 和 Comparator,他们之间有什么区别呢? ...
- 对象比较:Comparable 和 Comparator
java中我们如何给对象排序?这就必须借助Comparator 或 Comparable.有了他们就意味着你可用实现对象之间的比较.也就可用做到排序了. Comparable Comparable 也 ...
- Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)
1. Iterator迭代器 所有Collection的实现类都实现了iterator方法,该方法返回一个Iterator接口类型的对象,用于实现对集合元素迭代的便利.在java.util包下. 1) ...
- java compareto方法怎么排序的_深入理解Java中Comparable和Comparator排序
本文有牛旦教育原创,头条首发,转载注明来源. 如何为需要的排序算法选择正确的接口?通过本文的分析讲解,我们会找到答案参考答案. 程序员经常需要将数据库中的元素排序为集合.数组或映射.在Java中,我们 ...
- Java中Comparable和Comparator区别小结
阅读目录 一.Comparable简介 二.Comparator简介 三.Comparable和Comparator区别比较 回到顶部 一.Comparable简介 Comparable是排序接口.若 ...
- comparable和comparator比较
今天在翻阅TreeMap的源码,发现其键必须是实现Comparable或者Comparator的接口时产生了一些兴趣,比如在TreeMap中的put方法分别对Comparable和Comparat ...
- Java中Comparable与Comparator的区别
一.概述 Comparable和Comparator都是用来实现集合中元素的比较.排序的. Comparable是在集合内部定义的方法实现的排序,位于java.util下. Comparator是在集 ...
- Comparable与Comparator浅析
欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...
- Java中Comparable和Comparator接口区别分析
本文要来详细分析一下Java中Comparable和Comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的Java开发者继续看下去吧. Comparable 简介 Comp ...
最新文章
- java·环境变量、基本数据类型
- cad2016中选择全图字体怎么操作_LOL无限火力凯隐全图W技能BUG怎么卡 无限火力凯隐全图W技能BUG卡法介绍...
- 【收藏】如何查看linux服务器内存使用情况
- MySQL kill操作
- Composite(组合)--对象结构型模式
- 【Ubuntu】ubuntu系统下python3和python2环境自由切换
- 在spring boot中三分钟上手apache顶级分布式链路追踪系统skywalking
- 解决SQL查询总是 超时已过期
- 自适应谱线增强matlab,自适应谱线增强器.doc
- vivado 使用DDS IP方法
- c++ stl string char* 向 string 转换的问题
- XmlDataProvider的简单应用
- Wireshark入门:第一次亲密接触
- 傲腾内存不支持linux吗,内存英特尔® 傲腾™常见问题
- Mellanox网卡不能分配VF解决方法
- iAd框架详细解析 —— ASM
- ubuntu使用bitbucket
- Debian修改DNS
- VLAN规划原则与建议
- C# 简单判断枚举值是否被定义
热门文章
- laravel Ajax请求 X-CSRF验证问题
- 李瑾博士:信誉的建立是否“不计成本”?
- PostgreSQL导出导入schema相关
- css3ps—ps直接生成css3 使用方法
- Windows 無法查詢{7B849a69-220F-......} 的 DllName 登錄項目
- 考前必练15道题_《系统集成项目管理工程师备考宝典》
- 加速nginx: 开启gzip
- 20180529 Linux配置ip 排查问题
- MySQL存储引擎--MYSIAM和INNODB引擎区别
- 大数据技术将是传统企业创新的原点