IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Comparable接口和Comparator接口 -> 正文阅读

[数据结构与算法]Comparable接口和Comparator接口

前言

在实际应用中,我们往往有需要 比较两个自定义对象 大小的地方。而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的。所以 Java 中要 比较对象的大小 或者要 对对象的集合 进行排序,需要通过比较这些对象的某些属性的大小来确定它们之间的大小关系

一般 Java 中通过接口来实现两个对象的比较,比较常用就是 Comparable 接口和Comparator 接口

Comparable 接口

Comparable 接口使用场景

  • 一个类实现了 Comparable 接口,就意味着 该类支持排序,如果存在实现 Comparable 接口的类的 List 集合或 Array 数组,则该List 集合或 Array 数组可以通过 Collections.sortArrays.sort 来进行排序
  • 一个类实现了Comparable 接口,就意味着 该类支持两个对象比较大小

Comparable 接口源码

public interface Comparable<T> {
	
	public int compareTo(T o);
}
  • Comparable 可以让实现它的类的对象进行比较,具体的比较规则是按照 compareT()o 方法中的规则进行的,该方法的返回值有三种情况
  • e1.compareTo(e2) > 0e1 > e2
  • e1.compareTo(e2) = 0e1 = e2
  • e1.compareTo(e2) < 0e1 < e2

实现 Comparable 接口示例

  • 自定义类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConsumInfo implements Comparable<ConsumInfo> {

    private int uid;

    private double price;

    @Override
    public int compareTo(@NotNull ConsumInfo o) {
        if (price < o.price) {
            return -1;
        } else if (price > o.price) {
            return 1;
        } else {
            return 0;
        }
    }
}
  • 测试类:这里以对象的集合进行排序为例,当然也可以进行两个对象的大小比较
@Slf4j
public class ComparableTest {

    public static void main(String[] args) {

        ConsumInfo consumInfo1 = new ConsumInfo(100, 400.0);
        ConsumInfo consumInfo2 = new ConsumInfo(200, 200.0);
        ConsumInfo consumInfo3 = new ConsumInfo(300, 100.0);
        ConsumInfo consumInfo4 = new ConsumInfo(400, 700.0);
        ConsumInfo consumInfo5 = new ConsumInfo(500, 800.0);
        ConsumInfo consumInfo6 = new ConsumInfo(600, 300.0);
        ConsumInfo consumInfo7 = new ConsumInfo(700, 900.0);
        ConsumInfo consumInfo8 = new ConsumInfo(800, 400.0);

        List<ConsumInfo> list = new ArrayList<>();
        list.add(consumInfo1);
        list.add(consumInfo2);
        list.add(consumInfo3);
        list.add(consumInfo4);
        list.add(consumInfo5);
        list.add(consumInfo6);
        list.add(consumInfo7);
        list.add(consumInfo8);
        log.info("排序前:------");
        for (ConsumInfo consumInfo : list) {
            log.info("consumInfo为:" + consumInfo);
        }

        // 排序
        Collections.sort(list);
        log.info("排序后:------");
        for (ConsumInfo consumInfo : list) {
            log.info("consumInfo为:" + consumInfo);
        }
    }
}
  • 结果
00:16:09.316 [main] INFO org.example.test.ComparableTest - 排序前:------
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=100, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=200, price=200.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=300, price=100.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=400, price=700.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=500, price=800.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=600, price=300.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=700, price=900.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=800, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - 排序后:------
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=300, price=100.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=200, price=200.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=600, price=300.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=100, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=800, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=400, price=700.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=500, price=800.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=700, price=900.0)

Comparator 接口

Comparator 接口使用场景

  • 如果需要对某个 类的集合进行排序类对象比较大小,而该类本身又不能实现 Comparable 接口;那么,这时只需要实现 Comparator 接口即可

Comparator 接口源码

public interface Comparator<T> {

	int compare(T o1, T o2);
	
	boolean equals(Object obj);

	default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

	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);
        };
    }

	default <U> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        return thenComparing(comparing(keyExtractor, keyComparator));
    }

	default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }

	default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
        return thenComparing(comparingInt(keyExtractor));
    }

	default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
        return thenComparing(comparingLong(keyExtractor));
    }

	default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        return thenComparing(comparingDouble(keyExtractor));
    }

	public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

	public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }

	public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(true, comparator);
    }

	public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(false, comparator);
    }

	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));
    }

	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));
    }

	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));
    }

	public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
    }

	public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
    }
}

实现 Comparator 接口示例

  • 自定义类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConsumInfo implements Comparable<ConsumInfo> {

    private int uid;

    private double price;

    @Override
    public int compareTo(@NotNull ConsumInfo o) {
        // 首先比较price,如果price相同,则比较uid
        if (price < o.price) {
            return -1;
        } else if (price > o.price) {
            return 1;
        } else {
            return 0;
        }
    }
}
  • 具体的比较类(比较器),实现 Comparator 接口
public class ComparatorConsumInfo implements Comparator<ConsumInfo> {

    @Override
    public int compare(ConsumInfo o1, ConsumInfo o2) {
        // 首先比较price,如果price相同,则比较uid
        if (o1.getPrice() > o2.getPrice()) {
            return 1;
        }

        if (o1.getPrice() < o2.getPrice()) {
            return -1;
        }

        if (o1.getPrice() == o2.getPrice()) {
            if (o1.getUid() > o2.getUid()) {
                return 1;
            }
            if (o1.getUid() < o2.getUid()) {
                return -1;
            }
        }
        return 0;
    }
}
  • 测试类:这里以对象的集合进行排序为例,当然也可以进行两个对象的大小比较
@Slf4j
public class ComparatorTest {

    public static void main(String[] args) {

        ConsumInfo consumInfo1 = new ConsumInfo(100, 400.0);
        ConsumInfo consumInfo2 = new ConsumInfo(200, 200.0);
        ConsumInfo consumInfo3 = new ConsumInfo(300, 100.0);
        ConsumInfo consumInfo4 = new ConsumInfo(400, 700.0);
        ConsumInfo consumInfo5 = new ConsumInfo(500, 800.0);
        ConsumInfo consumInfo6 = new ConsumInfo(600, 300.0);
        ConsumInfo consumInfo7 = new ConsumInfo(700, 900.0);
        ConsumInfo consumInfo8 = new ConsumInfo(800, 400.0);

        List<ConsumInfo> list = new ArrayList<>();
        list.add(consumInfo1);
        list.add(consumInfo2);
        list.add(consumInfo3);
        list.add(consumInfo4);
        list.add(consumInfo5);
        list.add(consumInfo6);
        list.add(consumInfo7);
        list.add(consumInfo8);

        log.info("排序前:------");
        for (ConsumInfo consumInfo : list) {
            log.info("consumInfo为:" + consumInfo);
        }

        ComparatorConsumInfo comparatorConsumInfo = new ComparatorConsumInfo();
        Collections.sort(list, comparatorConsumInfo);
        log.info("排序后:------");
        for (ConsumInfo consumInfo : list) {
            log.info("consumInfo为:" + consumInfo);
        }
    }
}
  • 结果:如下图

在这里插入图片描述

Comparable 接口与 Comparator 接口对比

Comparable 接口

  • Comparable 位于包 java.lang
  • Comparable 接口将比较代码嵌入需要进行比较的类的自身中
  • Comparable 接口强制进行自然排序

Comparator 接口

  • Comparator 位于包 java.util
  • Comparator 接口在一个独立的类中实现比较,排序
  • 如果前期没有实现 Comparable 接口,后期可以通过 Comparator 接口来实现比较算法进行排序
  • Comparator 接口不强制进行自然排序,可以指定排序顺序,比如:升序、降序
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-07 12:17:52  更:2021-12-07 12:18:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:27:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码