可比接口和Comaprator接口

时间:2019-03-13 07:09:17

标签: java comparator comparable

一般说来,比较器用于具有对象集合的多个排序序列,而比较器用于具有单个排序序列。 当使用可比较的接口可以有多个排序序列时,java中的比较器接口有什么用?

import java.util.*;
enum CompareValue {RollNo, Marks;}
class Student implements Comparable<Student> {
    public int marks;
    public int rollNo;
    public static CompareValue comparator = CompareValue.RollNo;
    Student (int marks, int rollNo) {
        this.marks = marks;
        this.rollNo = rollNo;
    }
    public int compareTo(Student s) {
        switch (comparator) {
            case RollNo:
                return this.rollNo - s.rollNo;
            case Marks:
                return this.marks - s.marks;
        }
        return 0;
    }
}

public class Test
{
    public static void main (String[] args) 
    {
        Student s1 = new Student(59, 103);
        Student s2 = new Student(87, 102);
        Student s3 = new Student(78, 101);
        Student students[] = {s1, s2, s3};
        Arrays.sort(students);
        System.out.println("Student list sorted by rollno");
        for (Student s:students) {
            System.out.println(s.rollNo + " - " + s.marks);
        }
        Student.comparator = CompareValue.Marks;
        System.out.println("Student list sorted by marks");
        Arrays.sort(students);
        for (Student s:students) {
            System.out.println(s.rollNo + " - " + s.marks);
        }
    }
}

4 个答案:

答案 0 :(得分:1)

当您的compareTo方法基于某些static变量的值而具有不同的行为时,基本上就是在引入一个全局设置来控制Student类的自然顺序。

这可能会使您的类的用户感到迷惑和直觉。

此外,它使compareTo的实现尴尬,尤其是如果您有两个以上的实现,并且每个实现都依赖于多个实例变量。

Comparator是一个非常合适的接口,可以为同一类的实例提供多个不同的比较,每个实现都有自己的compare()逻辑。

答案 1 :(得分:0)

当您具有无法实现可比对象的对象,但您想对包含它们的集合进行排序时,您将不得不扩展它们以对集合进行排序,或者提供一个比较它们的比较器,即使它们不具有可比性。

或者您可能想要比较以自然排序方式不同的方式对这些对象进行排序。

想象一个例子。 字符串是可比较的对象。假设您要基于其hashCode而不是字符串自然顺序对字符串集合进行排序。在不创建比较器的情况下怎么办?

答案 2 :(得分:0)

您显示的内容确实是使用Comparable的多个排序顺序,但是您不认为这是太多的样板代码吗?假设您是否在名为name的类中添加了新字段,现在想按名称排序。您必须:

  • 向枚举添加新案例
  • compareTo添加一个新案例。

使用您展示的方法的另一个缺点是不一定清楚这意味着什么:

Arrays.sort(student);

您将必须仔细阅读代码,并检查已设置comparator的值。

此外,如果我正在使用您的课程,并且想按其他方式排序,则无论如何我都必须创建一个Comparator,因为我无法编辑您的课程。

但是,如果您使用Comparator,则可以解决所有这些问题:

Arrays.sort(students, Comparator.comparing(Student::getName));

因此,Comparable仅在存在一个一个自然顺序(例如日期和时间)时才有用。

答案 3 :(得分:0)

如果我们看一下Comparable和Comparator接口以及它们的含义,一切都会很清楚。

可比:

这是JAVA类的内部属性,即假定每当使用内部 compareTo()方法时,就会将其用于指定对象。

public int compareTo(T o);

因此,在此方法的实现中,我们使用this作为当前对象,并将其与其他相同类型的对象进行比较。这些可以被视为默认值或用于自然排序。
像1出现在2之前,依此类推。这是自然的顺序。

比较器:

这是实际上没有与Java类本身紧密绑定的属性。比较器用于实际提供一种方法,供其他一些服务(例如Collections.sort())用于实现特定目标。

int compare(T o1, T o2);

我们的意思是,您可以有多个比较器,以不同的方式实现不同的目标,其中实际服务可以选择任意两个对象并进行比较。
这可以用来提供自定义排序,例如使用某些方程式,我们可以得出一个排序,其中 f(1)实际上位于 f(2)之后,依此类推。这个方程很可能会实现一些解决用例的顺序。