• Java中的排序接口Comparable和比较器Comparator详解


    在java中经常涉及到对象数组的比较的情况,常见的有两种方法来处理:

    1. 自然排序: 继承comparable接口,并实现compareTo()方法
    2. 定制排序: 定义一个单独的对象比较器,继承自Comparator接口,实现compare()方法

    一、Comparable

    1.1、Comparable简介

    Comparable 是排序接口。(自然排序)
    若一个类实现了Comparable接口,就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。
    此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器

    1.2、Comparable 的典型实现:(默认都是从小到大排列的)

    1)String:按照字符串中字符的Unicode值进行比较
    2)Character:按照字符的Unicode值来进行比较
    3)数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
    4)Boolean:true 对应的包装类实例大于 false 对应的包装类实例
    5)Date、Time等:后面的日期时间比前面的日期时间大

    1.3、Comparable 定义

    Comparable 接口仅仅只包括一个函数,它的定义如下:

    1. package java.lang;
    2. import java.util.*;
    3. public interface Comparable {
    4. public int compareTo(T o);
    5. }

    解释: 假设我们通过 x.compareTo(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。

    这里为了大家更好的理解Compareable这个接口, 我自己手写了一个Compareable接口.

    案例1

    Comparable接口

    1. package com.company.strategy2;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public interface Comparable {
    7. public int compareTo(T object);
    8. }

    Cat实体类

    1. package com.company.strategy2;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class Cat implements Comparable {
    7. private int height;
    8. private int weight;
    9. public Cat(int height, int weight){
    10. this.height = height;
    11. this.weight = weight;
    12. }
    13. public int compareTo(Cat cat){
    14. if(this.height>cat.height){
    15. return 1;
    16. } else if(this.height
    17. return -1;
    18. } else{
    19. return 0;
    20. }
    21. }
    22. @Override
    23. public String toString() {
    24. return "Cat{" +
    25. "height=" + height +
    26. ", weight=" + weight +
    27. '}';
    28. }
    29. }

    Sorter类(手写排序算法, 这里用到的是冒泡排序)

    1. package com.company.strategy2;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class Sorter {
    7. public static void sort(Comparable[] arr) {
    8. if (arr == null || arr.length < 2) {
    9. return;
    10. }
    11. for (int e = arr.length - 1; e > 0; e--) {
    12. for (int i = 0; i < e; i++) {
    13. if (arr[i].compareTo(arr[i + 1]) == 1) {
    14. swap(arr, i, i + 1);
    15. }
    16. }
    17. }
    18. }
    19. public static void swap(Comparable[] arr, int i, int j) {
    20. Comparable temp = arr[i];
    21. arr[i] = arr[j];
    22. arr[j] = temp;
    23. }
    24. }

    测试类

    1. package com.company.strategy2;
    2. import java.util.Arrays;
    3. public class Main {
    4. public static void main(String[] args) {
    5. Cat[] cats = {new Cat(111,111), new Cat(555,555), new Cat(222,222), new Cat(444,444)};
    6. Sorter sorter = new Sorter();
    7. sorter.sort(cats);
    8. System.out.println(Arrays.toString(cats));
    9. }
    10. }

    实际使用中则不需要自己手写Comparable接口和sort排序算法.

    案例2:

    Pig实体类

    1. package com.company.strategy2;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-07
    5. */
    6. public class Pig implements java.lang.Comparable {
    7. private Double weight;
    8. public Pig(Double weight){
    9. this.weight = weight;
    10. }
    11. @Override
    12. public int compareTo(Pig pig) {
    13. if (this.weight>pig.weight) {
    14. return 1;
    15. } else if (this.weight
    16. return -1;
    17. } else {
    18. return 0;
    19. }
    20. }
    21. @Override
    22. public String toString() {
    23. return "Pig{" +
    24. "weight=" + weight +
    25. '}';
    26. }
    27. }

    测试类

    1. package com.company.strategy2;
    2. import java.util.Arrays;
    3. /**
    4. * Created by 苍狼
    5. * Time on 2022-08-07
    6. */
    7. public class Test {
    8. public static void main(String[] args) {
    9. Pig[] pigs = new Pig[]{new Pig(123.5), new Pig(145.6), new Pig(111.6)};
    10. System.out.println(Arrays.toString(pigs));
    11. Arrays.sort(pigs);
    12. System.out.println(Arrays.toString(pigs));
    13. }
    14. }

    运行结果 

    二、Comparator

    2.1、Comparator简介 

    1) 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排序的比较。
    2) 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
    3) 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
    4) 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

    2.2、Comparator定义

    Comparator 接口仅仅只包括两个个函数,它的定义如下:

    1. package java.util;
    2. public interface Comparator {
    3. int compare(T o1, T o2);
    4. boolean equals(Object obj);
    5. }

    解释: 若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。

    问题: 为什么可以不实现 equals(Object obj) 函数呢?

    因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。

    int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”

    同样的, 为了大家更加直观的理解, 我这里也同样写两个案例, 一个手写Comparator接口, 一个使用java提供的Comparator接口

    案例1:

    1. package com.company.strategy3;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. @FunctionalInterface //如果这里只有一个方法, 则这个也可以不写
    7. public interface Comparator {
    8. public int compare(T t1, T t2);
    9. default void show(){
    10. System.out.println("世界, 你好....");
    11. }
    12. }

    Cat实体类

    1. package com.company.strategy3;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class Cat{
    7. private int height;
    8. private int weight;
    9. public Cat(int height, int weight){
    10. this.height = height;
    11. this.weight = weight;
    12. }
    13. @Override
    14. public String toString() {
    15. return "Cat{" +
    16. "height=" + height +
    17. ", weight=" + weight +
    18. '}';
    19. }
    20. public int getHeight() {
    21. return height;
    22. }
    23. public void setHeight(int height) {
    24. this.height = height;
    25. }
    26. public int getWeight() {
    27. return weight;
    28. }
    29. public void setWeight(int weight) {
    30. this.weight = weight;
    31. }
    32. }

    cat的比较器类

    1. package com.company.strategy3;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class CatComparator implements Comparator{
    7. @Override
    8. public int compare(Cat t1, Cat t2) {
    9. if(t1.getHeight()*t1.getWeight()>t2.getHeight()*t2.getWeight()){
    10. return 1;
    11. } else if (t1.getHeight()*t1.getWeight()
    12. return -1;
    13. } else{
    14. return 0;
    15. }
    16. }
    17. }

    排序类Sorter中的sort排序方法

    1. package com.company.strategy3;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class Sorter {
    7. public void sort(T[] arr, Comparator comparator) {
    8. if (arr == null || arr.length < 2) {
    9. return;
    10. }
    11. for (int e = arr.length - 1; e > 0; e--) {
    12. for (int i = 0; i < e; i++) {
    13. if (comparator.compare(arr[i], arr[i+1])==1){
    14. swap(arr, i, i+1);
    15. }
    16. }
    17. }
    18. }
    19. public void swap(T[] arr, int i, int j) {
    20. T temp = arr[i];
    21. arr[i] = arr[j];
    22. arr[j] = temp;
    23. }
    24. }

    测试类

    1. package com.company.strategy3;
    2. import java.util.Arrays;
    3. public class Main {
    4. public static void main(String[] args) {
    5. Cat[] cats = {new Cat(111,111), new Cat(555,555), new Cat(222,222), new Cat(444,444)};
    6. Sorter sorter1 = new Sorter<>();
    7. sorter1.sort(cats, new CatComparator());
    8. System.out.println(Arrays.toString(cats));
    9. }
    10. }

    这里也可以用测试类Lambda表达式来写

    1. package com.company.strategy3;
    2. import java.util.Arrays;
    3. public class Main {
    4. public static void main(String[] args) {
    5. Sorter sorter = new Sorter();
    6. Cat[] cats= new Cat[]{new Cat(1111,1111), new Cat(8888,8888), new Cat(3333,3333), new Cat(6666,6666)};
    7. sorter.sort(cats, (o1,o2)->{
    8. if (o1.getHeight()>o2.getHeight()){
    9. return 1;
    10. } else if (o1.getHeight()
    11. return -1;
    12. } else{
    13. return 0;
    14. }
    15. });
    16. System.out.println(Arrays.toString(cats));
    17. }
    18. }

    案例2:

    Dog实体类

    1. package com.company.strategy3;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class Dog implements Comparable {
    7. private int food;
    8. public Dog(int food){
    9. this.food = food;
    10. }
    11. @Override
    12. public int compareTo(Dog dog) {
    13. if(this.food > dog.food){
    14. return 1;
    15. } else if (this.food < dog.food){
    16. return -1;
    17. } else{
    18. return 0;
    19. }
    20. }
    21. @Override
    22. public String toString() {
    23. return "Dog{" +
    24. "food=" + food +
    25. '}';
    26. }
    27. public void setFood(int food){
    28. this.food = food;
    29. }
    30. public int getFood(){
    31. return this.food;
    32. }
    33. }

    Dog的比较器类 

    1. package com.company.strategy3;
    2. /**
    3. * Created by 苍狼
    4. * Time on 2022-08-06
    5. */
    6. public class DogComparator implements Comparator{
    7. @Override
    8. public int compare(Dog t1, Dog t2) {
    9. if (t1.getFood()>t2.getFood()){
    10. return 1;
    11. } else if (t1.getFood()
    12. return -1;
    13. } else{
    14. return 0;
    15. }
    16. }
    17. }

    测试类

    1. package com.company.strategy3;
    2. import java.util.Arrays;
    3. /**
    4. * Created by 苍狼
    5. * Time on 2022-08-07
    6. */
    7. public class Test {
    8. public static void main(String[] args) {
    9. Dog[] dogs = new Dog[]{new Dog(111), new Dog(777), new Dog(555), new Dog(333)};
    10. System.out.println(Arrays.toString(dogs));
    11. System.out.println("=====================");
    12. Arrays.sort(dogs, new DogComparator());
    13. System.out.println(Arrays.toString(dogs));
    14. }
    15. }

    运行结果 

    Comparator 和 Comparable比较

    Comparable是排序接口: 若一个类实现了Comparable接口,就意味着“该类支持排序”。

    而Comparator是比较器: 我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。

    我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
     

  • 相关阅读:
    Postman - 设置变量
    Git 的基本操作 ——命令行
    技术解读倚天 ECS 实例 — Arm 芯片的 Python-AI 算力优化
    mysql中 COALESCE和CASE WHEN的使用以及创建或替换视图
    [附源码]java毕业设计学院竞赛管理信息系统
    WPF 属性触发器示例
    TCP/IP、DTN网络通信协议族
    中职计算机应用专业(云计算方向)建设实践
    Mysql数据库
    面向城市巡防的多无人机协同航迹规划
  • 原文地址:https://blog.csdn.net/m0_50370837/article/details/126207399