2017-02-17 100 views
2

目前,我正在学习“队列”接口的属性也碰到了下面的语句在Java Documentation比较“队列”中的Java对象

队列的实现一般并不定义基于元素的方法 equals和hashCode而是继承身份从Object类基于 版本,因为基于元素的平等是不 与相同的元素,但不同的 的排序属性的队列始终明确。

我不完全确定这个段落的意思,就如何比较相同实现类型和不同实现类型的“队列”对象而言。有人可以向我解释一下比较“队列”对象的方法吗?

回答

3

我觉得文档指出Queue实现通常不会覆盖默认从Object类的队列中的元素排序equals方法可以为每个执行有很大的不同,因此他们在一个通用的方法比较可能会出现意想不到的结果。

如果要根据自己的条件比较队列对象,可以实现Comparator<Queue>类(具体为compare方法)。然后,您可以使用此方法来直接比较两个队列,或者用它来排序队列集合等

javadoc for Comparator

1

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

这样做的原因行为(不重写equals)在Javadoc(你已经报吧)指出,这意味着是这样的:我们不能告诉如果1 2 3相同3 2 1因为元素的顺序队列可能很重要,所以请自行解决。

2

这里的困难是,队列确实有被订购的语义,但排序不总是在队列的迭代顺序清单。为有序集合定义equals()hashCode()几乎需要按元素的语义顺序迭代元素。如果你不能在它们的语义顺序遍历元素,你不能定义一个合理的equals()hashCode()合同。

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

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

原因是PriorityQueue是heap data structure存储在一个数组中。元素不按顺序存储。它们以符合堆不变量的方式存储,这比总排序要弱。有许多不同的方法可以将相同的元素存储在代表相同语义排序的堆中。您可以通过从队列中提取PriorityQueue的元素来获取它们的语义顺序中的元素 - 这具有销毁队列的副作用。

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