【问题标题】:Why do we use `this` in CompareTo in Comparable implementations?为什么我们在 Comparable 实现中的 CompareTo 中使用 `this`?
【发布时间】:2016-03-25 19:15:37
【问题描述】:

我对 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); 时,究竟会发生什么?

代码 sn-p 仅用于演示目的

【问题讨论】:

  • 为什么this.name 是空的?如果不知道构造函数是如何被调用的,你就无法知道this.name 的内容。

标签: java collections constructor comparator compareto


【解决方案1】:

你问的是两个不同的问题,所以我将分别回答它们

第一个是 我们试图通过比较 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 方法

【讨论】:

  • Collection.sort(empList) 认为列表是字符串类型。那么它里面的调用对象是什么?我猜empList.get(0).compareTo(empList.get(1)) 是这样进行比较的吗?
  • 调用对象取决于排序算法的具体实现。对于排序内部逻辑的每次迭代,它也会有所不同。例如,如果列表中有一个 StudentA,它可能在某些时候既是调用对象又是参数(不是同时)
【解决方案2】:

既然name 似乎是Student 的一个重要属性,您首先应该问自己的是“什么是学生的有效姓名?” null 有效吗?空字符串是否有效?如果没有,您需要使用 setter 来防止使用无效的 name 初始化 Student

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 值,则每次调用 compareTo() 方法时都会得到 NullPointerException。您实际上将调用null.compareTo(),显然null 没有这样的方法,它没有任何方法。

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

至于排序机制本身,它是特定于实现的,但它通常是几种算法的组合,一种混合​​。在 Java 中我相信它是 Timsort,在 C# 中它是自省排序。无论如何,为了像这样对集合进行排序,您需要两个两个地比较元素(因此需要实现Comparable)。诀窍是如何做到这一点,以减少执行的比较次数。有很多很好的资料可以解释不同的排序方法,但归根结底是能够比较元素并判断哪些应该在哪个之前。

【讨论】:

  • 您回答的第一部分虽然是值得考虑的好信息,但并未回答他提出的问题。
  • 问题不清楚,我尽力解释了。
  • 所以这是一个关于this使用的问题?对不起,我重读了好几遍,仍然无法弄清楚是否是这样。据我了解,他不清楚为什么他需要实现compareTo() 方法。
  • 我删除了我的最后一条评论,因为我意识到这很粗鲁抱歉,我知道你怎么会错过this 的重要性,因为标题没有特别格式化它,它只是读起来很尴尬没有意识到的句子
  • 是的,我认为措辞令人困惑。当英语不是您的母语时,要清楚地说明问题并不容易。如果提供的信息不是他想要的,我想作者可以在评论中要求澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 2019-05-02
  • 1970-01-01
相关资源
最近更新 更多