我正在学习队列收集,我不明白为什么在使用PriorityQueue时我需要实现Comparable接口?我在数组/列表的自定义排序中使用了Comparable和Comparator接口。但是,当我不想对它进行排序时,为什么我需要为PriorityQueue实现...
在下面的示例中,如果我没有实现Comparable接口,我发现我无法在PriorityQueue中添加元素。
对我来说很大的误解,在我运行此代码之后,列表没有按ID排序?我问这个问题因为我看到compareTo()方法被覆盖了,当我想对列表进行排序时我使用这个方法。
我记得当我为列表完成自定义排序时,我已经使用了exaclty这段代码。列表按id排序。为什么队列在这种情况下没有排序?
抱歉我的英语语法。任何反馈都会被贬低!
import java.util.PriorityQueue;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<Book> queue = new PriorityQueue<>();
//Creating Books
Book b1=new Book(121,"Let us C","Yashwant Kanetkar","BPB",8);
Book b2=new Book(233,"Operating System","Galvin","Wiley",6);
Book b3=new Book(101,"Data Communications & Networking","Forouzan","Mc Graw Hill",4);
Book b4=new Book(319,"Learn Java","Yanis Orhan","HEX",3);
Book b5=new Book(191,"Linux","Hadgy","Haman",7);
Book b6=new Book(287,"Python Programming","Tarzan","GEN",5);
//Adding Books to the queue
queue.add(b1);
queue.add(b2);
queue.add(b3);
queue.add(b4);
queue.add(b5);
queue.add(b6);
System.out.println("Traversing the queue elements:");
//Traversing queue elements
for(Book b : queue) {
System.out.println(b.id+" "+b.name+" "+b.author+" "+b.publisher+" "+b.quantity);
}
queue.remove();
System.out.println("After removing one book record:");
for(Book b : queue) {
System.out.println(b.id + " " + b.name + " " + b.author + " " + b.publisher + " " + b.quantity);
}
}
}
书
public class Book implements Comparable<Book> {
int id;
String name,author,publisher;
int quantity;
public Book(int id, String name, String author, String publisher, int quantity) {
this.id = id;
this.name = name;
this.author = author;
this.publisher = publisher;
this.quantity = quantity;
}
@Override
public int compareTo(Book b) {
if(id > b.id) {
return 1;
} else if (id < b.id) {
return -1;
} else {
return 0;
}
}
}
我看到头部是id最低的元素,但之后没有顺序。为什么队列没有按ID排序?
Traversing the queue elements:
101 Data Communications & Networking Forouzan Mc Graw Hill 4
191 Linux Hadgy Haman 7
121 Let us C Yashwant Kanetkar BPB 8
319 Learn Java Yanis Orhan HEX 3
233 Operating System Galvin Wiley 6
287 Python Programming Tarzan GEN 5
After removing one book record:
121 Let us C Yashwant Kanetkar BPB 8
191 Linux Hadgy Haman 7
287 Python Programming Tarzan GEN 5
319 Learn Java Yanis Orhan HEX 3
233 Operating System Galvin Wiley 6
更新
如果我创建一个ArrayList并使用相同的compareTo()方法对其进行排序,并使用相同的for-each循环打印它,则会对列表进行排序并按此顺序打印。
ArrayList的代码:
import java.util.ArrayList;
import java.util.Collections;
public class BookExample {
public static void main(String args[]) {
ArrayList<Book> bookList = new ArrayList<>();
Book b1=new Book(121,"Let us C","Yashwant Kanetkar","BPB",8);
Book b2=new Book(233,"Operating System","Galvin","Wiley",6);
Book b3=new Book(101,"Data Communications & Networking","Forouzan","Mc Graw Hill",4);
Book b4=new Book(319,"Learn Java","Yanis Orhan","HEX",3);
Book b5=new Book(191,"Linux","Hadgy","Haman",7);
Book b6=new Book(287,"Python Programming","Tarzan","GEN",5);
bookList.add(b1);
bookList.add(b2);
bookList.add(b3);
bookList.add(b4);
bookList.add(b5);
bookList.add(b6);
Collections.sort(bookList);
for (Book b : bookList) {
System.out.println(b.id + ", " + b.name + ", " + b.author + ", "
+ b.publisher + ", " + b.quantity);
}
}
}
书
public class Book implements Comparable<Book> {
int id;
String name, author, publisher;
int quantity;
public Book(int id, String name, String author, String publisher, int quantity) {
this.id = id;
this.name = name;
this.author = author;
this.publisher = publisher;
this.quantity = quantity;
}
public int compareTo(Book b) {
if(id > b.id) {
return 1;
} else if (id < b.id) {
return -1;
} else {
return 0;
}
}
}
控制台中的结果:
101, Data Communications & Networking, Forouzan, Mc Graw Hill, 4
121, Let us C, Yashwant Kanetkar, BPB, 8
191, Linux, Hadgy, Haman, 7
233, Operating System, Galvin, Wiley, 6
287, Python Programming, Tarzan, GEN, 5
319, Learn Java, Yanis Orhan, HEX, 3
为什么打印ArrayList时for-each循环工作得非常好,当我尝试打印PriorityQueue时它不起作用?
答案 0 :(得分:5)
方法iterator()中提供的迭代器无法保证以任何特定顺序遍历优先级队列的元素。如果您需要有序遍历,请考虑使用
Arrays.sort(pq.toArray())
。
因此,您不能只使用for(Book book: queue)
循环。
您可以按照Javadoc中的建议复制到临时数组中,或者(如果您不介意在此过程中销毁队列)循环遍历poll()
。
我同意这是违反直觉的。他们可能根本不应该实现Iterable
......
答案 1 :(得分:0)
PriorityQueue
用于特定目的:允许您从队列中获取最高“优先级”项目,而不管其添加顺序如何。您提供的比较仅用于确定“优先级”。在订单中迭代的意义上,它不是一个有序的集合。
您可以依次删除项目并进行比较来测试。您会发现删除它们的顺序是由您定义的比较定义的。
答案 2 :(得分:0)
PriorityQueue
,javadoc读
基于优先级堆的无界优先级队列。优先级队列的元素根据其自然顺序排序,或者由队列构造时提供的比较器排序,具体取决于使用的构造函数。优先级队列不允许null元素。依赖于自然排序的优先级队列也不允许插入不可比较的对象(这样做可能会导致ClassCastException)。
在将新元素添加到队列时,需要一种比较元素的方法,以便正确地确定元素的优先级。
要按顺序打印队列,您需要使用以下建议:
如果需要有序遍历,请考虑使用Arrays.sort(pq.toArray())。
P / S:我想你只想在java中实现Queue
接口,然后突然跳转到PriorityQueue
。
在这种情况下,ArrayDeque<>
最符合您的需求。
答案 3 :(得分:-1)
List和PriorityQueue之间的区别在于,List通过插入来保持元素的排序,而另一方面,PriorityQueue会根据您的情况(ID)按照您希望的属性来排序元素。如果您要插入的元素无法相互比较,则PriorityQueue行为默认为列表的行为。