我如何让一个PriorityQueue对我想要它排序的东西进行排序?
另外,在提供和添加方法之间有区别吗?
我如何让一个PriorityQueue对我想要它排序的东西进行排序?
另外,在提供和添加方法之间有区别吗?
当前回答
我还想知道打印订单的问题。举个例子:
对于优先级队列:
PriorityQueue<String> pq3 = new PriorityQueue<String>();
这段代码:
pq3.offer("a");
pq3.offer("A");
可能打印不同于:
String[] sa = {"a", "A"};
for(String s : sa)
pq3.offer(s);
我从另一个论坛的讨论中找到了答案,其中一个用户说,“offer()/add()方法只将元素插入队列。如果你想要一个可预测的顺序,你应该使用peek/poll来返回队列的头。”
其他回答
没有区别,正如在javadoc中声明的那样:
public boolean add(E e) {
return offer(e);
}
Java 8解决方案
我们可以使用Java 8中引入的lambda表达式或方法引用。如果我们有一些String值存储在优先队列中(容量为5),我们可以提供内联比较器(基于String的长度):
使用lambda表达式
PriorityQueue<String> pq=
new PriorityQueue<String>(5,(a,b) -> a.length() - b.length());
使用方法参考
PriorityQueue<String> pq=
new PriorityQueue<String>(5, Comparator.comparing(String::length));
然后我们可以使用它们中的任何一个:
public static void main(String[] args) {
PriorityQueue<String> pq=
new PriorityQueue<String>(5, (a,b) -> a.length() - b.length());
// or pq = new PriorityQueue<String>(5, Comparator.comparing(String::length));
pq.add("Apple");
pq.add("PineApple");
pq.add("Custard Apple");
while (pq.size() != 0)
{
System.out.println(pq.remove());
}
}
这将打印:
Apple
PineApple
Custard Apple
要反转顺序(将其更改为max-priority queue),只需在inline comparator中更改顺序或使用reversed as:
PriorityQueue<String> pq = new PriorityQueue<String>(5,
Comparator.comparing(String::length).reversed());
我们也可以使用Collections.reverseOrder:
PriorityQueue<Integer> pqInt = new PriorityQueue<>(10, Collections.reverseOrder());
PriorityQueue<String> pq = new PriorityQueue<String>(5,
Collections.reverseOrder(Comparator.comparing(String::length))
我们可以看到集合。reverseOrder重载以获取比较器,这对自定义对象很有用。反转函数实际上使用Collections.reverseOrder:
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
Offer () vs add()
根据文件
offer方法尽可能插入一个元素,否则返回 假的。这与合集不同。方法,该方法可能失败 仅通过抛出未经检查的异常来添加元素。报价 方法是为失败是正常使用而设计的,而不是 异常发生,例如在固定容量(或“有界”)中 队列。
在使用有容量限制的队列时,offer()通常比add()更可取,后者只能通过抛出异常而无法插入元素。PriorityQueue是一个基于优先级堆的无界优先级队列。
只是为了回答add() vs offer()问题(因为另一个问题在我看来已经完美回答了,这可能不是):
根据接口Queue上的JavaDoc,“offer方法尽可能插入一个元素,否则返回false。这与合集不同。方法,该方法只能通过抛出未经检查的异常来添加元素。offer方法设计用于故障是正常情况,而不是异常情况,例如在固定容量(或“有界”)队列中。”
That means if you can add the element (which should always be the case in a PriorityQueue), they work exactly the same. But if you can't add the element, offer() will give you a nice and pretty false return, while add() throws a nasty unchecked exception that you don't want in your code. If failure to add means code is working as intended and/or it is something you'll check normally, use offer(). If failure to add means something is broken, use add() and handle the resulting exception thrown according to the Collection interface's specifications.
它们都是通过这种方式实现的,以便在Queue接口上通过返回false(在有容量限制的队列中首选的方法)来指定offer()失败,并在Collection接口上通过抛出异常来维护add()总是失败的契约。
无论如何,希望这至少澄清了问题的那一部分。
给它一个比较器。在T的位置填入你想要的类型
Java 8+:
int initialCapacity = 10;
PriorityQueue<T> pq = new PriorityQueue<>(initialCapacity, (e1, e2) -> { return e1.compareTo(e2); });
经典的方法,使用匿名类:
int initialCapacity = 10;
PriorityQueue<T> pq = new PriorityQueue<>(initialCapacity, new Comparator<T> () {
@Override
public int compare(T e1, T e2) {
return e1.compareTo(e2);
}
});
要按相反的顺序排序,只需交换e1和e2。
在这里,我们可以定义用户定义的比较器:
以下代码:
import java.util.*;
import java.util.Collections;
import java.util.Comparator;
class Checker implements Comparator<String>
{
public int compare(String str1, String str2)
{
if (str1.length() < str2.length()) return -1;
else return 1;
}
}
class Main
{
public static void main(String args[])
{
PriorityQueue<String> queue=new PriorityQueue<String>(5, new Checker());
queue.add("india");
queue.add("bangladesh");
queue.add("pakistan");
while (queue.size() != 0)
{
System.out.printf("%s\n",queue.remove());
}
}
}
输出: 印度 巴基斯坦 孟加拉国
提供和添加方法的区别:链接