【问题标题】:Comparing "Queue" objects in Java比较 Java 中的“队列”对象
【发布时间】:2017-02-17 03:16:01
【问题描述】:

我目前正在研究“队列”接口的属性,在Java Documentation遇到了如下语句:

队列实现通常不定义基于元素的版本 方法的 equals 和 hashCode 而是继承基于身份的 Object 类的版本,因为基于元素的相等性不是 总是为具有相同元素但不同的队列定义良好 排序属性。

关于如何比较相同实现类型和不同实现类型的“队列”对象,我不确定这一段的含义。有人可以向我解释如何比较“队列”对象吗?

【问题讨论】:

    标签: java collections queue


    【解决方案1】:

    我认为文档说明 Queue 实现通常不会覆盖 Object 类中的默认 equals 方法,因为每个实现 Queue 中元素的顺序可能会有很大差异,因此以通用方式比较它们可能会产生意想不到的结果.

    如果您想根据自己的标准比较 Queue 对象,您可以实现 Comparator<Queue> 类(特别是 compare 方法)。然后,您可以使用此方法直接比较两个队列,或者使用它对队列集合进行排序等。

    javadoc for Comparator

    【讨论】:

      【解决方案2】:

      这里的困难在于队列确实具有被排序的语义,但排序并不总是体现在队列的迭代顺序中。为有序集合定义 equals()hashCode() 几乎需要按语义顺序迭代元素。如果不能按语义顺序迭代元素,就无法定义合理的equals()hashCode() 合约。

      PriorityQueue 就是一个很好的例子。元素的语义顺序由提供的比较器或元素的自然顺序定义。但是,PriorityQueue 的迭代顺序是undefined!

      迭代器不会以任何特定顺序返回元素。

      原因是 PriorityQueue 是 heap data structure 存储在数组中的。元素没有按顺序存储。它们以满足堆不变量的方式存储,这比总排序弱。有许多不同的方式可以将相同的元素存储在表示相同语义顺序的堆中。您可以通过从队列中提取它们来按语义顺序获取 PriorityQueue 的元素——这具有破坏队列的副作用。

      我想可以通过使用语义顺序并应用类似于List 的规则来定义队列的equals()hashCode()。对于 PriorityQueue,这需要创建数组的临时副本并在每次调用时对其进行排序。我怀疑这太繁重了;许多程序员会惊讶地发现计算 PriorityQueue 的哈希码需要 O(n log n) 时间和 O(n) 临时空间。出于这个原因,我怀疑 Queue 的 equals()hashCode() 未指定,以便从 Object 继承基于身份的版本。

      【讨论】:

        【解决方案3】:

        默认实现中的队列通过引用进行比较(Object 类中的默认实现)。因此,如果要比较队列,则必须覆盖 equals,或者可以将队列转换为其他集合(例如,列表或集合或数组)并进行比较,从实现的角度来看,这会更容易一些。

        这种行为的原因(不覆盖equals)在javadoc中说明(你已经引用了它),这意味着:我们无法判断1 2 3是否与3 2 1相同,因为排序队列中的元素可能很重要,所以请自己弄清楚。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-09
          相关资源
          最近更新 更多