我如何让一个PriorityQueue对我想要它排序的东西进行排序?
另外,在提供和添加方法之间有区别吗?
我如何让一个PriorityQueue对我想要它排序的东西进行排序?
另外,在提供和添加方法之间有区别吗?
当前回答
作为使用Comparator的替代方法,您还可以让您在PriorityQueue中使用的类实现Comparable(并相应地重写compareTo方法)。
注意,如果排序是对象的直观排序,那么通常最好只使用Comparable而不是Comparator——例如,如果您有一个用例要按年龄对Person对象排序,那么可能最好只使用Comparator。
import java.lang.Comparable;
import java.util.PriorityQueue;
class Test
{
public static void main(String[] args)
{
PriorityQueue<MyClass> queue = new PriorityQueue<MyClass>();
queue.add(new MyClass(2, "short"));
queue.add(new MyClass(2, "very long indeed"));
queue.add(new MyClass(1, "medium"));
queue.add(new MyClass(1, "very long indeed"));
queue.add(new MyClass(2, "medium"));
queue.add(new MyClass(1, "short"));
while (queue.size() != 0)
System.out.println(queue.remove());
}
}
class MyClass implements Comparable<MyClass>
{
int sortFirst;
String sortByLength;
public MyClass(int sortFirst, String sortByLength)
{
this.sortFirst = sortFirst;
this.sortByLength = sortByLength;
}
@Override
public int compareTo(MyClass other)
{
if (sortFirst != other.sortFirst)
return Integer.compare(sortFirst, other.sortFirst);
else
return Integer.compare(sortByLength.length(), other.sortByLength.length());
}
public String toString()
{
return sortFirst + ", " + sortByLength;
}
}
输出:
1, short
1, medium
1, very long indeed
2, short
2, medium
2, very long indeed
其他回答
使用构造函数重载,它接受Comparator<?super E>比较器,并传入一个比较器,它会按照排序顺序进行比较。如果你给出一个你想要如何排序的例子,如果你不确定的话,我们可以提供一些示例代码来实现比较器。(其实很简单。)
正如在其他地方所说:offer和add只是不同的接口方法实现。在JDK源代码中,添加calls offer。虽然add和offer通常具有潜在的不同行为,因为offer能够表示由于大小限制而不能添加值,但这种差异在PriorityQueue中是无关的,因为PriorityQueue是无界的。
下面是一个优先级队列按字符串长度排序的例子:
// Test.java
import java.util.Comparator;
import java.util.PriorityQueue;
public class Test {
public static void main(String[] args) {
Comparator<String> comparator = new StringLengthComparator();
PriorityQueue<String> queue = new PriorityQueue<String>(10, comparator);
queue.add("short");
queue.add("very long indeed");
queue.add("medium");
while (queue.size() != 0) {
System.out.println(queue.remove());
}
}
}
// StringLengthComparator.java
import java.util.Comparator;
public class StringLengthComparator implements Comparator<String> {
@Override
public int compare(String x, String y) {
// Assume neither string is null. Real code should
// probably be more robust
// You could also just return x.length() - y.length(),
// which would be more efficient.
if (x.length() < y.length()) {
return -1;
}
if (x.length() > y.length()) {
return 1;
}
return 0;
}
}
输出如下:
短 媒介 确实很长
下面是一个简单的例子,你可以用它来进行初步学习:
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
public class PQExample {
public static void main(String[] args) {
//PriorityQueue with Comparator
Queue<Customer> cpq = new PriorityQueue<>(7, idComp);
addToQueue(cpq);
pollFromQueue(cpq);
}
public static Comparator<Customer> idComp = new Comparator<Customer>(){
@Override
public int compare(Customer o1, Customer o2) {
return (int) (o1.getId() - o2.getId());
}
};
//utility method to add random data to Queue
private static void addToQueue(Queue<Customer> cq){
Random rand = new Random();
for(int i=0;i<7;i++){
int id = rand.nextInt(100);
cq.add(new Customer(id, "KV"+id));
}
}
private static void pollFromQueue(Queue<Customer> cq){
while(true){
Customer c = cq.poll();
if(c == null) break;
System.out.println("Customer Polled : "+c.getId() + " "+ c.getName());
}
}
}
给它一个比较器。在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。
我还想知道打印订单的问题。举个例子:
对于优先级队列:
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来返回队列的头。”
作为使用Comparator的替代方法,您还可以让您在PriorityQueue中使用的类实现Comparable(并相应地重写compareTo方法)。
注意,如果排序是对象的直观排序,那么通常最好只使用Comparable而不是Comparator——例如,如果您有一个用例要按年龄对Person对象排序,那么可能最好只使用Comparator。
import java.lang.Comparable;
import java.util.PriorityQueue;
class Test
{
public static void main(String[] args)
{
PriorityQueue<MyClass> queue = new PriorityQueue<MyClass>();
queue.add(new MyClass(2, "short"));
queue.add(new MyClass(2, "very long indeed"));
queue.add(new MyClass(1, "medium"));
queue.add(new MyClass(1, "very long indeed"));
queue.add(new MyClass(2, "medium"));
queue.add(new MyClass(1, "short"));
while (queue.size() != 0)
System.out.println(queue.remove());
}
}
class MyClass implements Comparable<MyClass>
{
int sortFirst;
String sortByLength;
public MyClass(int sortFirst, String sortByLength)
{
this.sortFirst = sortFirst;
this.sortByLength = sortByLength;
}
@Override
public int compareTo(MyClass other)
{
if (sortFirst != other.sortFirst)
return Integer.compare(sortFirst, other.sortFirst);
else
return Integer.compare(sortByLength.length(), other.sortByLength.length());
}
public String toString()
{
return sortFirst + ", " + sortByLength;
}
}
输出:
1, short
1, medium
1, very long indeed
2, short
2, medium
2, very long indeed