Comparable和Comparator两种比较器详解

简介: Comparable和Comparator两种比较器详解

【1】java.lang.Comparable

Comparable,翻译一下为可比较的。从汉语词义来看,通常是表明对象特性,即该对象是可比较的。实现了该接口的类的实例对象就可以进行自然排序,该实例对象的集合或者数组就可以使用Collections.sort或Arrays.sort方法进行自然排序。

接口源码如下:

package java.lang;
import java.util.*;
public interface Comparable<T> {
    int compareTo(T var1);
}

实现了该接口的类实例对象可以作为SortedMap的key或者SortedSet的元素,而无需使用一个额外的比较器-Comparator。


强烈推荐自然排序结果与equals方法保持一致(虽然不是一定的),即自然排序时两个对象相等条件为 e1.equals(e2)返回true时,e1.compareTo(e2) == 0。另外需要注意的是null对象不是任何一个类的实例对象,所以e.compareTo(null)应该抛出NullPointerException,即使e.equals(null)返回false。


如果compareTo方法与对象的equals方法比较结果不一致时 ,那么在使用SortedMap、SortedSet这类没有明确比较器的集合时就会很奇怪。尤其是将会违反集合的基本约定–根据equals方法判断集合元素是否相等。


然而并不 严格要求(x.compareTo(y)==0) == (x.equals(y))。一般说来,任何违背这个条件的实现都应该明确指出这一事实情况。


实际上,实现Comparable的所有Java核心类都具有与equals一致的自然顺序。一个例外是java.math.BigDecimal,其自然顺序等同于具有相同值和不同精度(例如4.0和4.00)的大十进制对象。


int compareTo(T var1);方法会比较两个实例对象,0表示相等,正数表示大于,负数表示小于。

实现该方法一定要注意以下事项:


必须保证sgn(x.compareTo(y)) ==-sgn(y.compareTo(x)) 。

必须保证比较的顺序关系是可传递的,如果x.compareTo(y)>0 而且y.compareTo(z)>0 则x.compareTo(z)>0。

如果存在x.compareTo(y)=0,则对于 z 而言,存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。


Comparable 的典型实现:


BigDecimal、BigInteger 以及所有的数值型对应的包装类:按它们对应的数值大小进行比较

Character:按字符的 unicode值来进行比较

Boolean:true 对应的包装类实例大于 false 对应的包装类实例

String:按字符串中字符的 unicode 值进行比较

Date、Time:后边的时间、日期比前面的时间、日期大

【2】java.util.Comparator

首先第一点不同的就是,包不同了!Comparable是在java.lang包中,而Comparator是在java.util中。


第二点不同的是Comparator被显示作为一个函数式接口,其上有@FunctionalInterface注解。其只有两个抽象方法(compare和equals)但是提供了很多默认方法和静态方法。


Java 8中允许接口中包含具有具体实现的方法,该方法称为“默认方法”,默认方法使用default关键字修饰。而且Default方法只在接口中被允许使用。

Java8 中,接口中允许添加静态方法,可以直接被使用。

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);
  default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }
//...
}

Comparator比较器可以被使用在Collections.sort或 Arrays.sort方法中允许对排序顺序进行精确控制。Comparator同样可以被使用在SortedSet、SortedMap以及对其他自身没有自然排序属性的实例对象上。


同Comparable一样,Comparator的compare方法返回结果应该与equals方法返回结果保持一致。即,c.compare(e1, e2)==0时e1.equals(e2)。


不过建议谨慎使用Comparator,因为该比较器可以强制排序与使用equals方法排序集合不一致。


实现Comparator的compare方法需要保证以下几点:


必须保证sgn(compare(x, y)) ==-sgn(compare(y, x))

必须保证比较的顺序关系是可传递的,如果compare(x,y)>0 而且compare(y,z)>0 则 compare(x,z)>0。

如果存在 compare(x,y)=0,则对于 z 而言,存在 compare(x, z)==compare(y, z)。

强烈推荐compare(x,y)方法返回结果与x.equals(y)方法返回结果保持一致。然而并不 严格要求(compare(x, y)==0) == (x.equals(y))。一般说来,任何违背这个条件的 Comparator 实现都应该明确指出这一事实情况。


使用实例如下

@Test
  public void test4(){
    List<Integer> integers=new ArrayList<>();
    integers.add(1);
    integers.add(2);
    integers.add(3);
    //匿名内部类
    integers.sort(new Comparator<Integer>() {
      @Override
      public int compare(Integer o1, Integer o2) {
        return o1.compareTo(o2);
      }
    });
    //lambda表达式
    integers.sort((o1,o2)->o1.compareTo(o2));
//    Comparator<Integer> integerComparator = Integer::compareTo;
    //方法引用
    integers.sort(Integer::compareTo);
    integers.sort(Comparator.comparing(Integer::intValue));
  }


目录
相关文章
|
SQL 监控 关系型数据库
MySQL怎么全局把一张表的数据回滚
MySQL怎么全局把一张表的数据回滚
1118 2
解决Swagger UI 中文乱码问题
解决办法如下: 1、file --> Settings --> file encodings 2、在弹出的对话框右侧,将所有的Encoding(一共四个已经标红)全部改为**“UTF-8”**
1206 0
|
消息中间件 数据采集 域名解析
数据采集-Lua集成kafka流程跑通|学习笔记
快速学习数据采集-Lua集成kafka流程跑通
数据采集-Lua集成kafka流程跑通|学习笔记
|
3月前
|
缓存 人工智能 NoSQL
Java中实现Token设置过期时间的方法
本文介绍了在Java应用中实现Token设置过期时间的多种方法,包括使用JWT和Redis缓存,并结合定时任务清理过期Token,以提升系统安全性与用户隐私保护。
353 0
|
定位技术
Echarts实战案例代码(10):echarts结合世界所有国家地图数据集geojson的(英文翻译映射)解决方案
Echarts实战案例代码(10):echarts结合世界所有国家地图数据集geojson的(英文翻译映射)解决方案
1243 0
Echarts实战案例代码(10):echarts结合世界所有国家地图数据集geojson的(英文翻译映射)解决方案
|
人工智能 vr&ar Android开发
深入探索安卓与iOS的未来发展
【10月更文挑战第8天】 本文将深入探讨安卓和iOS两个主流操作系统的未来发展,从技术创新、用户体验和市场竞争等多个角度进行分析,揭示它们在技术演进中的趋势以及面临的挑战。
222 3
|
10月前
|
人工智能 安全 搜索推荐
OA办公的未来:从工具到流程的深度整合
在企业数字化转型中,“效率”至关重要。多人协同编辑(如板栗看板)突破传统文档处理方式,解决了信息孤岛、重复劳动和信息不透明等协作瓶颈,提供即时同步、可追溯、灵活及安全的编辑体验。它作为现代化OA系统的核心模块,通过优化文档协作、流程和知识管理,以及组织间的协作,显著提升多部门工作效率,缩短定稿周期,并支持跨区域无缝对接。未来,该技术将向智能化发展,集成AI辅助、跨平台融合和个性化配置等功能,为企业创造更大价值。
|
存储 Java 数据库
SpringBoot整合Spring Data Elasticsearch
Spring Data Elasticsearch提供了ElasticsearchTemplate工具类,实现了POJO与elasticsearch文档之间的映射
530 0
|
监控 Kubernetes Linux
在Linux中,如何排查性能下降问题?
在Linux中,如何排查性能下降问题?
|
存储 缓存 编译器
面向未来:理解ARM处理器的新一代技术(下)
面向未来:理解ARM处理器的新一代技术