为啥有些人使用 PriorityQueue 覆盖比较器函数来实现 minheap,即使 Java 中的 PQ 默认是最小堆?

Posted

技术标签:

【中文标题】为啥有些人使用 PriorityQueue 覆盖比较器函数来实现 minheap,即使 Java 中的 PQ 默认是最小堆?【英文标题】:Why do some people override the comparator function for implementing minheap using PriorityQueue even though PQ in java is a min-heap by default?为什么有些人使用 PriorityQueue 覆盖比较器函数来实现 minheap,即使 Java 中的 PQ 默认是最小堆? 【发布时间】:2019-02-06 06:34:17 【问题描述】:

我搜索了一下,看起来像 PriorityQueue 在 Java 中默认情况下像最小堆一样工作。那么,为什么要覆盖比较器?我见过人们甚至对整数也这样做。我在这里错过了什么吗?我是java新手。

我尝试了以下两个代码以在需要 min-heap 实现的 leetcode 解决方案中使用,并且都被接受了。这是一个sn-p:

// Implementing comparator
PriorityQueue<Integer> minHeap = new PriorityQueue<>(10,new Comparator<Integer>() 
    public int compare(Integer a, Integer b) 
        return a - b;
    
);

// Not implementing comparator - why can't we just do this?
PriorityQueue<Integer> minHeap = new PriorityQueue<>();

【问题讨论】:

a) 他们不知道自己在做什么,然后从某个地方复制粘贴。 b)确实知道他们在做什么,但想要提醒它默认使用的顺序 了解原因的唯一方法是询问那些人。这里的任何答案都是猜测。 谢谢。我想知道是否有一些我不知道的技术解释。 【参考方案1】:

在这种情况下,Comparator 确实显得多余。如果你没有明确地将Comparator 传递给PriorityQueue 的构造函数,它将使用自然排序,这正是Comparator 实现的。

【讨论】:

不完全是。使用a - b 的比较器显然是为了和自然顺序一样做,但实际上是broken,因为这个减法可能会溢出。两个int 值之间的最大距离可能超过Integer.MAX_VALUE。可能这段代码的作者甚至故意用这个替换了自然顺序,认为这是对直接的int比较的“聪明”优化,在这种情况下,打破这个可能是一项艰巨的任务开发者的习惯……

以上是关于为啥有些人使用 PriorityQueue 覆盖比较器函数来实现 minheap,即使 Java 中的 PQ 默认是最小堆?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能将 PriorityQueue 存储到 MongoDB 中

`PriorityQueue` 中的 `add` 和 `addAll` 行为不同,这是为啥呢?

为啥有些人在通信中使用 Class#method 而不是 Class.method?

java - 为啥在java中的poll方法之后PriorityQueue中的值会发生变化? [复制]

我用的是AD13。我现在转换为CAD之后,PCB中自动覆铜部分丢失,为啥?

Java之集合PriorityQueue