可比较和比较器接口

问题描述 投票:1回答:4

通常说比较器用于具有多个对象集合的排序序列,而可比较用于具有单个排序序列。当使用类似的接口可以有多个排序序列时,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);
        }
    }
}
java comparator comparable
4个回答
1
投票

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

这可能会让您的班级用户感到困惑和反直觉。

此外,它使得compareTo的实现变得笨拙,特别是如果你有两个以上的实现,并且每个实现依赖于多个实例变量。

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


0
投票

如果您的对象没有实现可比性,但您希望对包含它们的集合进行排序,则您必须扩展它们以仅对集合进行排序或提供比较它们的比较器,即使它们不具有可比性。

或者您可能希望比较那些对象以不同的方式对它们进行自然排序。

想象一下这样的例子。 String是一个可比较的对象。想象一下,您希望根据hashCode而不是字符串自然顺序对字符串集合进行排序。如果不创建比较器,你会怎么做?


0
投票

您所展示的确实存在使用Comparable的多个排序顺序,但您认为它不是太多锅炉板代码吗?假设您已经在名为name的类中添加了一个新字段,现在您想按名称排序。你必须:

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

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

Arrays.sort(student);

您必须查看代码并检查您设置comparator的值。

另外,如果我正在使用你的课程,而我想用其他东西排序,我还是要创建一个Comparator,因为我无法编辑你的课程。

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

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

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


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)之后,依此类推。该等式可能会实现一些解决用例的顺序。

© www.soinside.com 2019 - 2024. All rights reserved.