【问题标题】:How Comparator.compare() works?Comparator.compare() 如何工作?
【发布时间】:2019-03-01 20:19:09
【问题描述】:

学习 Kotlin,我试图了解 Java 的 Comparator 接口是如何工作的 - 主要是 compare() 函数,以便我可以使用它。

我已尝试阅读 compare() 的文档,但我希望对其工作原理进行更简单的解释。

在遍历列表时,compare(x, y) 中的 xy 到底是什么?它在迭代时是否针对并比较每对数字?例如:

arrayOf(1, 2, 3, 4)

它会比较 1 和 2(x 和 y),然后是 2 和 3(x 和 y),然后是 3 和 4(x 和 y)吗?

我有一个 Kotlin 函数,它提供了一个比较器来按降序对列表进行排序:

import java.util.*

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, object: Comparator<Int> {
        override fun compare(x: Int, y: Int){
            return x < y
        }
    } )
    return arrayList

我不确定为什么上面的函数不是完成它的正确语法。

【问题讨论】:

标签: java kotlin


【解决方案1】:

归结为javadoc的这句话:

比较它的两个参数的顺序。返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个参数。

这就是全部。编写 Comparator 时,您定义您想要的顺序。关键是您的方法返回 -1、0 或 1。这取决于您希望如何对这两个传入参数进行排序。 (是的,它不需要 -1 或 1,只需负数、零、正数)。

换句话说:关键是compare() 在该合同中服务。它定义了两个元素的order。这就是全部。

对数据进行排序时,每次底层排序代码需要知道两个元素的顺序时都会调用它。因此,这些调用发生的确切“顺序”以及传递的参数取决于实际的排序算法以及您打算排序的数据。

从这个角度来看,您的问题暗示您对整个主题有些过度思考。简单理解:当您打算为您的对象/值定义“自定义”顺序时,您会使用比较器。

为 int、Int 或 Integer 定义“自己的”比较器是没有意义的,因为这些类已经定义了它们的自然顺序,因此例如已经有 Integer.compare()。为此类定义自己的比较器的唯一用例是当您想以不同的方式对它们进行排序时。但最有可能的是,您仍会使用现有的比较器功能,并使用其他内置方式,例如反转“自然”顺序。

【讨论】:

  • 请注意,严格来说,返回任何正值或负值都可以,惯例是在可行的情况下返回1-1
  • @biziclop 相应地调整了答案。
  • 哦,我的印象是排序更灵活。是不是很简单:正=升,负=降?
  • @Zorgan 再次:排序基于顺序。您定义应该使用的顺序。 返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个参数。 按升序排列,5 小于 10,因此为“负数”。如果要降序,则应在 10 之后订购 5,因此是正数。希望这是有道理的。
  • 但是您不能选择如何“排序”这些数字 - 只有 xy 来自未知列表? @鬼猫
【解决方案2】:

Comparator&lt;T&gt; 只是一种比较 T 类型的任意 2 个元素的方法。

遍历列表时 compare(x, y) 中的 x 和 y 到底是什么?

迭代时,根本不调用比较器。

当传递给Collections.sort() 方法时,只要底层排序算法需要比较两个元素,就会使用比较器。

我不确定为什么上面的函数不是完成它的正确语法。

您当前的实现不满足documentationcompare() 需要返回负整数、0 或正整数,具体取决于 2 个元素如何相互关联。

【讨论】:

    【解决方案3】:

    Comparator 只是可以比较的类的接口。这是关于比较任何两个对象。不多也不少。来自文档:

    @param o1 要比较的第一个对象。

    @param o2 要比较的第二个对象。

    @return 一个负整数、零或一个正整数作为 第一个参数小于、等于或大于 第二个。

    排序完全是另一回事。它使用比较器(在不知道如何比较两个元素的情况下很难对任何内容进行排序),因此您可以提供自己的方式对集合进行排序。

    但它是如何排序的?关于通过Collections.sort(collection, comparator) 进行排序,我们所知道的只是排序是稳定的。查看更多关于排序的信息:https://www.geeksforgeeks.org/sorting-algorithms/

    【讨论】:

      【解决方案4】:

      compare 文档非常清楚:

      返回负整数、零或正整数作为第一个 参数小于、等于或大于秒。

      因此,您必须从函数中返回 Int 而不是布尔值。

      为了提供有效的 Kotlin 代码,我举了一个例子:

      val list = listOf(1, 5, 2)
      list.sortedWith(Comparator { x, y ->
             x.compareTo(y)
      })
      

      排序本身可以使用不同的算法执行,但它们将在内部使用compareToCollections 文档给出了一个想法:

      本文档中包含的多态算法的文档 类通常包括对实现的简要描述。 此类描述应被视为实施说明,而不是 比规范的部分。实施者应该随意 替代其他算法,只要规范本身是 坚持。 (例如 sort 使用的算法不必 是一个归并排序,但它必须是稳定的。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-04
        • 2018-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-23
        • 2016-11-16
        相关资源
        最近更新 更多