【问题标题】:How to understand the order induced by the comparator in Java?如何理解 Java 中比较器引发的顺序?
【发布时间】:2021-07-08 22:52:35
【问题描述】:

我对 Java 中的比较器和 Collections.sort() 感到非常困惑。 我不明白比较器引起的顺序。我不清楚比较函数应该返回哪个数字来获取排序方向。我也不知道 Collections 将如何使用该比较结果对输入数据进行排序。我应该背诵它们吗?有什么更容易理解的吗?任何人都可以为我解释一下吗?谢谢。

public int compare(Obj a, Obj b){ 
    if(a.age > b.age) return 1; 
    if(a.age < b.age) return -1;
    else              return 0;
}

更新

在从一些友好的软件工程师那里得到一些解释后,我了解到比较器定义了集合中元素的顺序。例如,当比较 a 和 b 时,如果比较器返回 -1,那么在列表中 a 应该放在 b 之前。

【问题讨论】:

  • 我的助记词是:return a.age - b.age,将ab在减法中的顺序与在参数列表中的顺序相同,那么它将给出正确的排序结果递增顺序。如果age 是一个int,其值从0 到140,这是正确的。由于int 上溢和下溢,对于任意int 值是不正确的,但我的助记符在所有情况下都能很好地确定何时返回负值以及何时返回正值(它们不必是1 和- 1).

标签: java comparator


【解决方案1】:

步骤 1

一种简化和关联的方法可能是您的代码:

public int compare(Obj a, Obj b){ 
    if(a.age > b.age) return 1; 
    if(a.age < b.age) return -1;
    else              return 0;
}

将表示如下(假设ageint 变量)

public int compare(Obj a, Obj b) {
    return Integer.compare(a.getAge(), b.getAge());
}

Integer.compare 在内部执行与您之前执行相同的逻辑:

return (x < y) ? -1 : ((x == y) ? 0 : 1)

第二步

现在这可以使用比较器进一步表示为:

Comparator<Obj> ageComparator = Comparator.comparingInt(Obj::getAge);

Comparator.comparingInt 内部执行

return (Comparator<T> & Serializable)
        (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));

因此,例如,当您调用时,所有这三种形式最终导致的顺序是相同的

objList.sort(ageComparator);

ComparablecompareTo方法可以在比较部分详细说明

Compares this object with the specified object for order.  Returns a
negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.

因此,当您覆盖 compareTo 扩展为 Comparable&lt;Obj&gt; 时,这被认为是 Obj自然排序

【讨论】:

  • 我想问为什么比较器返回-1那么排序的结果会升序。为什么不是相反?
  • @MinhTriLe 使用比较器,这是输入的自然顺序。 (升序)这是您比较两个后续元素以确定其中一个大于/等于/小于另一个。
  • 好的,我明白了。所以当比较器比较一个列表中的2个后续元素a1、a2时,如果结果为-1,则表示a1小于a2,所以它们不会被交换,那么顺序是升序的。
  • @MinhTriLe 您在上面的评论中说“如果结果为-1,则表示 a1 小于 a2”。最好是“如果结果为-1,则表示a1在a2之前”。
  • 好的,我明白了。非常感谢。
【解决方案2】:

要对一组项目进行排序,我们应该能够比较该组中的每一对项目,并判断哪个“更大”,哪个“更小”。

想象一下,您的任务是手动对以下数字进行排序。

4、2、7、8、3

你会如何运用你的思想来完成这项任务?您必须查看成对的数字并比较它们,然后找出要放在乞讨处的最小数字。

同样,为了完成排序任务,计算机需要比较成对的项目,然后判断哪个“更大”,哪个“更小”。

所以,我们写的比较器对象是“定义”,哪个更大哪个更小。当我们对数字进行排序时,这个定义应该说哪个更大,哪个更小。当我们对字符串进行排序时,这个定义应该说明字母表中哪个字母在前,哪个字母在后。

【讨论】:

  • 我明白,我只是不明白为什么如果比较器返回-1那么顺序会升序。
  • 是的,比较器定义了“顺序”。它没有说升序或降序。如果compareTo(object1, object2) 返回-1,则依次是object1 和object2。
【解决方案3】:

要记住的关键是如果比较返回正值 (>0) 会发生交换。否则不在排序算法期间。

例子:

4(a) 2(b) 6

升序:

a > b (4 > 2) 返回 1(需要在 a 和 b 之间交换,即放置 2 4 6)

降序:

a > b (2 > 4) return -1(在 a 和 b 之间不需要交换,即放置 4 2 6,因为它已经按顺序排列)。

这个逻辑是在排序算法下实现的,所以,只要想一想如果 a 和 b 已经按照你的预期排序然后返回 -1 否则返回 1。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多