排序 Comparable接口、Comparator接口

String类的Comparable接口

1String类实现了Comparable<String>接口,并提供了compareTo方法的实现,

  因此,字符串对象(即String类型的实例)可以直接调用compareTo()方法来比较它们。

2String类的compareTo()方法是这样工作的:
    
    它按照字典顺序比较两个字符串,
    
    从两个字符串的第一个字符开始比较,如果它们相等,则继续比较下一个字符,
    
    直到找到不同的字符或者到达字符串的末尾,
    
    如果所有的字符都相同,那么较短的字符串被认为是较小的。



排序

Comparable接口


"实现Comparable接口 ,就必须重写它的compareTo()方法"

"Comparable接口"是一个泛型接口,在类的声明中使用泛型参数,来指定需要比较的对象类型,
  
  它包含一个compareTo()方法,如下所示:
    public interface Comparable<T> {
      int compareTo(T o);
    }

  "compareTo()方法",返回一个整数值,用于表示当前对象,与另一个对象的比较结果。通常,它有以下三种返回值:
		
		如果,当前对象 小于 另一个对象,则返回,负整数。
		
		如果,当前对象 等于 另一个对象,则返回,零。
		
		如果,当前对象 大于 另一个对象,则返回,正整数。


使用的场景:
	1、具体的类A,实现Comparable接口
	2、重写Comparable接口中的compareTo(Object obj)方法,在此方法中指明比较类A的对象的大小的标准
	3、创建类A的多个实例,进行大小的比较或排序。

实现Comparable接口
要使一个类可以进行自然排序,需要实现"Comparable接口"并提供"compareTo()方法的具体实现",在compareTo()方法中,你需要指定对象之间的比较规则,

如:
"Student.java"
public class Student implements Comparable<Student> {
  private String name;
  private int age;

  public Student(String name, int age) {
    this.name = name;
    this.age = age;
  }

  @Override
  public int compareTo (Student other){
    return this.age - other.age;
  }

  public String toString() {
    return "Student{name='" + name + "', age=" + age + '}';
  }
}
Student类实现了Comparable<Student>接口,并重写了compareTo()方法,按照年龄升序排序,是通过比较当前对象的年龄属性和另一个对象的年龄属性来实现的。

"MyTest.java"
import java.util.TreeSet;
public class MyTest {
  public static void main(String[] args) {
    TreeSet<Student> studentSet = new TreeSet<>();
    studentSet.add(new Student("Alice", 22));
    studentSet.add(new Student("Bob", 20));
    studentSet.add(new Student("Charlie", 25));

    for (Student student : studentSet) {
        System.out.println(student);
    }
  }
}
/* 打印结果如下:
  Student{name='Bob', age=20}
  Student{name='Alice', age=22}
  Student{name='Charlie', age=25}
*/

"对上面的代码做一下解释"Java中,当你创建一个实现了Comparable接口的类的实例,并将其放入一个TreeSet集合时,

  TreeSet会自动使用该类实现的compareTo()方法来对集合中的元素进行排序,
  
  你不需要显式地调用compareTo()方法,
  
  因为,TreeSet内部在需要时会自动调用它。

  另:
    1、创建TreeSet实例:
      当你创建 "TreeSet<Student> studentSet" 时,实际上是在告诉Java你想要一个有序的、不重复的集合,该集合将包含Student类型的对象。

    2、添加元素到TreeSet:
      当你调用 "studentSet.add(new Student("Alice", 22))" 等方法添加元素时,
      TreeSet内部会检查新元素与集合中已存在元素的顺序关系,
      这是通过调用新元素的compareTo方法实现的。

    3、自动排序:
      在TreeSet内部,元素是以红黑树的结构存储的,
      当你添加一个新元素时,TreeSet会使用compareTo()方法来确定新元素在树中的正确位置,以保持集合的有序性,
      这个过程是自动的,你不需要显式地调用任何排序方法。

    4、遍历TreeSet:
      当你遍历TreeSet时(使用for-each循环),你会看到元素已经按照compareTo方法定义的顺序排列好了。

    这个例子中,
    Student类实现了Comparable<Student>接口,并重写了compareTo方法,
    该方法比较两个Student对象的age属性,
    因此,当你将Student对象添加到TreeSet时,它们会按照年龄升序排列。

Collections.sort
"Student.java"
public class Student implements Comparable<Student>{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Student other) {
        return this.age - other.age;
    }

    public String toString() {
        return "Student{name='" + name + "', age=" + age + '}';
    }
}


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Test1 {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("Alice", 22));
        list.add(new Student("White", 18));
        list.add(new Student("Black", 30));

        // 使用了Collections.sort()方法,对学生列表进行了排序
        Collections.sort(list);

        for (Student stu : list){
            System.out.println(stu);
        }
        /*
          打印结果为:
            Student{name='White', age=18}
            Student{name='Alice', age=22}
            Student{name='Black', age=30}

        * 使用了Collections.sort()方法,对学生列表进行了排序,
        * 因为,Student类实现了 Comparable 接口,
        * 所以,它根据年龄属性自动进行了升序排序。
        * */
    }
}

为什么 Collections.sort(list) 会使用 Student类的compareTo()方法进行排序呢?
  因为,Student类实现了Comparable<Student>接口并重写了compareTo()方法,
  所以,当你调用 Collections.sort(list)时,该方法会自动调用,Student类中的compareTo()方法,来比较对象并进行排序。


自定义排序
"要求"
  有时,需要对对象进行多属性排序,例如,
  先按年龄升序排序,然后按姓名字母顺序排序,
  为了实现多属性排序,可以在 compareTo()方法中逐一比较不同属性,确保按照所需顺序比较。

"Person.java"
public class Person implements Comparable<Person>{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person other) {
        // 先按年龄升序
        int ageComparison = this.age - other.age;
        if (ageComparison != 0) {
            return ageComparison;
        }

        // 如果年龄相等,则按照名字字母排序
        return this.name.compareTo(other.name);
    }

    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + '}';
    }
}


import java.util.Collections;
import java.util.List;
public class PersonTest {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("Wang", 26));
        list.add(new Person("King", 19));
        list.add(new Person("He", 19));
        list.add(new Person("Black", 28));

        /*
          为了对列表进行排序,需要调用Collections.sort()方法,并传递您的Person列表作为参数,
          因为,Person类实现了Comparable<Person>接口,并定义了比较逻辑,
          所以,Collections.sort()方法将能够使用Person类中的compareTo()方法来对列表进行排序。
        */
        Collections.sort(list);

        for (Person per : list) {
            System.out.println(per);
        }
        /*
        * 打印结果为:
            Student{name='He', age=19}
            Student{name='King', age=19}
            Student{name='Wang', age=26}
            Student{name='Black', age=28}
        * */
    }
}



Comparator定制排序

什么时候使用?
  
  当,元素的类型没有实现java.lang.Comparable接口,而又不方便修改代码(比如JDK当中的类),
  
  或者,实现了java.lang.Comparable接口,但定义好的排序规则不适合当前的操作,
  
  那么,可以考虑使用接口Comparator的对象来排序,强行对多个对象进行整体排序的比较。


1public interface Comparator<T>
  Comparator属于接口且支持范型,位于java.util包下

2Comparator接口,内置实现自定义排序的抽象方法compare()int compare(T o1,T o2)T:泛型,这个方法是让两个形参对象去比较大小。

  重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
    如果,返回,正整数,则表示o1大于o2
    
    如果,返回0,表示相等
    
    如果,返回负整数,表示 o1小于o2
    
    需要在compare中指明o1和o2按照什么规则比较

3、
  可以将Comparator传递给sort方法(如 Collections.sort或Arrays.sort),从而允许在排序顺序上实现精确控制。

  还可以使用 Comparator 来控制某些数据结构(如有序set 或 有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

Arrays类下的sort方法

  public static <T> void sort(T[] a, Comparator<? super T> c)

对基本数据类型的排序
import java.util.Arrays;
import java.util.Comparator;

public class TestComparator {
    public static void main(String[] args) {
        Integer[] arr1 = {1,4,2,3};

        // 降序
        Arrays.sort(arr1, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(Arrays.toString(arr1)); // [4, 3, 2, 1]

        // 升序
        Arrays.sort(arr1, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        System.out.println(Arrays.toString(arr1)); // [1, 2, 3, 4]
    }
}

对象数组的排序
"StuComparator.java"
public class StuComparator {
    String name;
    int age;
    double height;

    public StuComparator() {
    }

    public StuComparator(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "\n" + "name=" + name + ", age=" + age + ", height=" + height + " \n";
    }
}

"TestStuComparator.java"
import java.util.Arrays;
import java.util.Comparator;
public class TestStuComparator {
    public static void main(String[] args) {
        StuComparator[] stu = new StuComparator[4];
        stu[0] = new StuComparator("张三", 16, 176.6);
        stu[1] = new StuComparator("李四", 25, 181.3);
        stu[2] = new StuComparator("小明", 18, 179.4);
        stu[3] = new StuComparator("小红", 17, 165);

        // 以年龄排序
        Arrays.sort(stu, new Comparator<StuComparator>() {
            @Override
            public int compare(StuComparator o1, StuComparator o2) {
                return o1.age - o2.age;
            }
        });
        System.out.println(Arrays.toString(stu));
        /*
            [
                name=张三, age=16, height=176.6
                ,
                name=小红, age=17, height=165.0
                ,
                name=小明, age=18, height=179.4
                ,
                name=李四, age=25, height=181.3
            ]
        */


        // 以身高排序
        Arrays.sort(stu, new Comparator<StuComparator>() {
            @Override
            public int compare(StuComparator o1, StuComparator o2) {
                return Double.compare(o1.height, o2.height);
            }
        });
        System.out.println(Arrays.toString(stu));
        /*
            [
                name=小红, age=17, height=165.0
                ,
                name=张三, age=16, height=176.6
                ,
                name=小明, age=18, height=179.4
                ,
                name=李四, age=25, height=181.3
            ]
        */
    }
}

相关推荐

  1. 排序 Comparable接口Comparator接口

    2024-03-13 14:34:02       39 阅读
  2. 排序时Collections.sort和Comparator区别

    2024-03-13 14:34:02       53 阅读
  3. 排序列表 原生方法和comparator方法

    2024-03-13 14:34:02       31 阅读
  4. 智能成绩表---重点 覆写comparator排序compare函数

    2024-03-13 14:34:02       43 阅读
  5. ComparableComparator,你学会了吗?

    2024-03-13 14:34:02       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-13 14:34:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-13 14:34:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-13 14:34:02       87 阅读
  4. Python语言-面向对象

    2024-03-13 14:34:02       96 阅读

热门阅读

  1. python爬取drugbank

    2024-03-13 14:34:02       43 阅读
  2. 人工智能的迷惑行为:一场技术与期望的较量

    2024-03-13 14:34:02       48 阅读
  3. C#多态例讲

    2024-03-13 14:34:02       42 阅读
  4. VC下显示位图的几种方法

    2024-03-13 14:34:02       30 阅读
  5. C语言代码 判断输入的字符是不是字母

    2024-03-13 14:34:02       40 阅读
  6. c#检查两个时间段是否重叠

    2024-03-13 14:34:02       45 阅读
  7. .NET CORE Aws S3 使用

    2024-03-13 14:34:02       36 阅读
  8. 【R3F】11.模型加载

    2024-03-13 14:34:02       41 阅读
  9. 修改ubuntu的子网掩码

    2024-03-13 14:34:02       43 阅读
  10. 神经网络中的先验知识

    2024-03-13 14:34:02       44 阅读
  11. 什么是网站服务器?

    2024-03-13 14:34:02       45 阅读