Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

    • Java基础

    • Java进阶

      • 类的初始化与对象的初始化
      • Object类
      • 深度理解字符串String
      • Integer创建对象分析
      • 从原理上分析 i = i++ 与 i = ++i
      • Comparable和Comparator的区别
        • Comparable
        • Comparator
        • 总结
      • 四种引用介绍
      • 静态代理与动态代理
      • 位运算
    • Java容器

    • Java并发编程

    • Java虚拟机

    • 常见面试题

  • 计算机基础

  • 框架|中间件

  • 架构

  • 后端
  • Java
  • Java进阶
Marvel
2022-07-14
目录

Comparable和Comparator的区别

# Comparable和Comparator区别

# Comparable

自然排序:comparable接口出自java.lang包,它有一个compareTo(Object obj)方法用来排序。

像String,包装类等实现了Comparable接口,重写了compareTo()方法。对于自定义类,如果需要排序的话,可以让自定义类实现Comparable接口,在compareTo()方法中指明如何排序。

重写compareTo(obj)规则:

  • 如果当前对象this > 形参对象obj,返回正整数。

  • 如果当前对象this < 形参对象obj,返回负整数。

  • 如果当前对象this = 形参对象obj,返回零。

我们来看看String的源码:

// 实现了 Comparable 接口,说明String对象可以进行排序
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    ...
    // 实现了compareTo方法,通过这个方法比较两个字符串的大小
    // 具体的比较方式就是比较每个字符的ASCCII,细节就不展开了。
	public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

我们对一组字符串进行排序:

String[] arr = new String[]{"AA", "ZZ", "DD", "XX", "CC"};
Arrays.sort(arr);
for (String s : arr) {
    System.out.println(s);
}
1
2
3
4
5

输出的顺序为:AA、CC、DD、XX、ZZ

如果我们想要对字符串进行倒序排列该怎么办呢?或者对没有实现Comparable接口的类进行排序该怎么办?那就要使用定制排序Comparator。

# Comparator

定制排序:comparator接口出自 java.util包,它有一个compare(Object obj1, Object obj2)方法用来排序。

当元素的类型没有实现Comparable接口又不方便修改时,或者实现了Compareble接口的排序规则不适合当前的操作,那么可以使用Comparator对象来排序。重写compare(Object o1, Object o2)。可以将Comparator传递给sort方法(如Collections.sort()和Arrays.sort())。

先对上面的字符串数组进行倒序排列:

String[] arr = new String[]{"AA", "ZZ", "DD", "XX", "CC"};
Arrays.sort(arr, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return -o1.compareTo(o2);
    }
});
for (String s : arr) {
    System.out.println(s);
}
1
2
3
4
5
6
7
8
9
10

输出的顺序为:ZZ、XX、DD、CC、AA

上面的代码可以通过lambda表达式和函数式编程进行简化:

String[] arr = new String[]{"AA", "ZZ", "DD", "XX", "CC"};
Arrays.sort(arr, (o1, o2) -> -o1.compareTo(o2));
Arrays.stream(arr).forEach(System.out::println);
1
2
3

可以看看稍微复杂一点的案例,有下面一个二维数组,需要按从大到小的顺序排列,第0位大的数组排在前面,第0位相同时,第1位大的数排在前面。

int[][] arr = new int[][]{{2, 4}, {4, 3}, {2, 7}, {0, 1}, {2,5}, {1, 3}};
Arrays.sort(arr, (o1, o2) -> {
    if (o1[0] == o2[0]) {
        return o2[1] - o1[1];
    } else {
        return o2[0] - o1[0];
    }
});
for (int[] a : arr) {
    System.out.println(a[0] + ", " + a[1]);
}
1
2
3
4
5
6
7
8
9
10
11

# 总结

  • Comparable 形容词,表示这个类具有比较的能力,Comparator 名词,比较器
  • Comparable 相当于内部比较器,Comparator 相当于外部比较器
  • 使用Comparable需要修改源码;使用Comparator不需要修改源码,而需要另外实现比较方法
编辑 (opens new window)
#Java
上次更新: 2023/08/20, 21:21:52
从原理上分析 i = i++ 与 i = ++i
四种引用介绍

← 从原理上分析 i = i++ 与 i = ++i 四种引用介绍→

最近更新
01
位运算
05-21
02
二叉树
05-12
03
Spring三级缓存解决循环依赖
03-25
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Marvel
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式