Article directory
- 1. Features of PriorityQueue
- 2. Introduction to common interfaces of PriorityQueue
- Three, PriorityQueue source code analysis
- 1. Small and heap source code analysis
- 2. PriorityQueue is a small heap by default. How can it become a large heap?
- 3. How does the Integer data type become a large heap? (self-implementing comparator)
- 4. Source code analysis of PriorityQueue expansion
- 4. Summary
- Five, the comparison method of PriorityQueue in the collection framework
1. Features of PriorityQueue
The Java collection framework provides two types of priority queues, PriorityQueue and PriorityBlockingQueue. PriorityQueue is thread-unsafe, and PriorityBlockingQueue is thread-safe.
Note on the use of PriorityQueue:
1. When using, you must import the package where PriorityQueue is located, namely:
import java.util.PriorityQueue;
2. The elements placed in the PriorityQueue must be able to compare the size, and cannot insert objects that cannot be compared, otherwise a
ClassCastException will be thrown
public static void main(String[] args) {
PriorityQueue<Student> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(new Student(10));
}
//这个时候虽然是不能比较的,但是此时运行也没有报错,那是因为此时只有一个对象,是不需要进行比较的
public static void main(String[] args) {
PriorityQueue<Student> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(new Student(10));
priorityQueue.offer(new Student(5));
}
//但是此时运行就会报错了,因为此时这两个对象是无法进行比较的
At this point, there are two solutions, one is to give the comparator, the other is to implement the Comparable interface and override the compareTo method.
At this point we choose to implement the Comparable interface and override the compareTo method:
class Student implements Comparable<Student>{
public int age;
public Student(int age){
this.age = age;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
3. Null objects cannot be inserted, otherwise NullPointerException will be thrown
4. There is no capacity limit, any number of elements can be inserted, and its internal capacity can be automatically expanded
5. The time complexity of inserting and deleting elements is O(log2N) (log takes 2 as the N at the bottom)
6. The bottom layer of PriorityQueue uses a heap data structure
7. PriorityQueue is a small heap by default - that is, the elements obtained each time are the smallest elements
2. Introduction to common interfaces of PriorityQueue
1. The construction of the priority queue
Constructor | Features |
PriorityQueue() | Creates an empty priority queue with a default capacity of 11 |
PriorityQueue(int initialCapacity) |
Create a priority queue with initialCapacity, note: initialCapacity cannot be less than 1, otherwise an IllegalArgumentException will be thrown |
PriorityQueue(Collection<? extends E> c) |
Use a collection to create a priority queue |
2. Insert / delete / get the element with the highest priority
Function name | Features |
boolean offer(E e) |
Insert element e, and return true if the insertion is successful. If the e object is empty, a NullPointerException will be thrown. The time complexity is O(log2N) (log is N with the base of 2). Note: when the space is not enough, the capacity will be expanded |
E peek() | Get the element with the highest priority, or return null if the priority queue is empty |
E poll() | Remove the element with the highest priority and return, or null if the priority queue is empty |
int size() | Get the number of valid elements |
void clear() |
empty |
boolean isEmpty() |
Check if the priority queue is empty, return true if empty |
Three, PriorityQueue source code analysis
1. Do source code analysis for the following three lines (small root heap):
PriorityQueue<Student> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(new Student(10));
priorityQueue.offer(new Student(5));
PriorityQueue<Student> priorityQueue = new PriorityQueue<>();The source code analysis of this line of code is as follows:
priorityQueue.offer(new Student(10));Next, let's look at the source code of the first offer:
priorityQueue.offer(new Student(5));
Next, let's look at the source code of the second offer:
2. PriorityQueue is a small root heap by default. How can it become a large root heap?
By modifying the comparison rules, it can become a large root heap.
There are two ways:
First, through our source code analysis above, we can modify the comparison rules, which can be modified to < ; but we cannot modify the source code, so I will directly look at the second method.
The second is: modify the comparison rules in the rewritten comparaTo method:
public int compareTo(Student o) {
return this.age - o.age;
}
3. How does the Integer data type become a large heap? (self-implementing comparator)
The first step is to implement the comparator by yourself:
class IntComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
//return o2 - o1;
return o2.compareTo(o1);
}
}
The second step is to pass in the comparator when passing parameters:
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new IntComparator());
At this point, when we run the program again, it is already a big heap.
Let's analyze the source code:
4. Source code analysis of PriorityQueue expansion
private void grow(int minCapacity) {
int oldCapacity = queue.length;
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
// overflow-conscious code
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
If the capacity is less than 64, it is expanded according to 2 times of oldCapacity.
If the capacity is greater than or equal to 64, it is expanded according to 1.5 times of oldCapacity.
If the capacity exceeds MAX_ARRAY_SIZE ( 2147483639 ), expand according to MAX_ARRAY_SIZE
4 Summary
1. When the array capacity is not passed in, the default is 11
2. When no comparator is passed in, the passed in objects must be comparable, otherwise an error will be reported
3. The priority is to use the comparator to compare
5 Comparison of PriorityQueue in Collection Framework
Overridden method | explain |
Object.equals
|
Because all classes inherit from
Object
, they can be overridden directly, but they can only be compared for equality and
no
|
Comparable.compareTo
|
The interface needs to be implemented manually, which is more intrusive, but once implemented, there is an order for each use of the class, which belongs to the internal order
|
Comparator.compare
|
A comparator object needs to be implemented, which is less invasive to compare classes, but more invasive to algorithm code implementation |