为什么我们在Comparable实现中的CompareTo中使用`this`?

时间:2016-03-25 19:15:37

标签: java collections constructor comparator compareto

我对java有点新,对Collection框架来说还是新手。我知道this指的是当前对象

public class Student implements Comparable <Student> {

    String name;
    int grade;

    public Student(String name, int grade) {
        this.name = name;
        this.grade = grade;
    }
    public int compareTo(Student s) {
         return this.name.compareTo(s.name);
    }
    public String toString() {
        return this.name + ", " + this.grade;
    }
}

此处this.name为空且s.name确实有值,因此我们通过比较this.name.compareTo(s.name);

尝试做什么

当我们Collections.sort(studentList);时,会发生什么?

代码段仅用于演示目的

2 个答案:

答案 0 :(得分:4)

你问两个不同的问题,所以我会单独回答它们

第一个是我们通过比较this.name.compareTo(s.name);

尝试什么

当在类Student的对象上调用compareTo方法时, this 成为调用对象。由于调用对象(希望)已经正确初始化,因此this.name将是调用对象的名称。

s.name是传递给compareTo方法的Student对象的名称,该方法再次(希望)正确初始化并具有名称。

什么是归结为一个String变量调用compareTo传入一个String变量来与

进行比较

第二个是当我们做Collections.sort(studentList)时真正发生的事情;

以下是Collections.Sort method上的JavaDocs,但您可能会询问它与您的Comparable实现相关的功能。简而言之,它在进行排序

的比较时使用compareTo方法

答案 1 :(得分:2)

由于似乎nameStudent的重要属性,首先你要问自己的是“学生的名字是什么?” null有效吗?空字符串有效吗?如果没有,则需要使用setter阻止使用无效Student初始化name

public void setName(String name) {
  if (name is invalid) {
    throw error;
  }

  this.name = name; // name is valid, so this is safe now
}

现在,在构造函数中调用setter,如果你有Student,你就会确定他有一个有效的name

使用无效name的一个问题是,如果您不阻止null值,则每次调用NullPointerException方法时都会获得compareTo()。你基本上是在调用null.compareTo(),显然null没有这样的方法,它没有任何方法。

现在,使用sort()方法。你如何排序Student?如果您没有告诉Java如何将一个Student与另一个Student进行比较,那么它应该如何排序?它可以处理数字(2小于3)和字符串(“a”在“b”之前),但它不知道如何比较您创建的自定义类。因此,您需要使用compareTo()方法让它知道。在无法比较的对象集合上调用sort()将导致异常。在sort()集合上调用Student将使用您在compareTo()中提供的规则(name(常规字符串比较))对其进行排序。

至于排序机制本身,它是特定于实现的,但它通常是几种算法的组合,一种混合​​。在Java中我相信它是Timsort,在C#中它是内省的排序。在任何情况下,为了对这样的集合进行排序,您需要逐个比较元素(因此需要实现Comparable)。诀窍是如何做到这一点,以减少执行比较的次数。有很多很好的资源来解释不同的排序方法,但这一切都归结为能够比较元素并告诉它应该在哪个之前。

相关问题