Explain Codes LogoExplain Codes Logo

Change priorityQueue to max priorityQueue

java
priority-queue
comparators
java-8
Nikita BarsukovbyNikita Barsukov·Dec 4, 2024
TLDR

Here's how to turn a PriorityQueue into a max heap. Use a Comparator to reverse the order.

Handy code, in case of integers:

PriorityQueue<Integer> maxPQ = new PriorityQueue<>(Collections.reverseOrder());

Dealing with custom objects? No problem! Reverse the order using a comparator on the relevant field:

PriorityQueue<MyObject> maxPQ = new PriorityQueue<>((o1, o2) -> o2.compareTo(o1));

Don't forget! Replace compareTo with your field's comparator method.

Coding a mini max with comparators

Comparators define the order in a PriorityQueue. To code a max priority queue, create comparators putting higher values first. Wondering how? Consider initial trial:

Comparator<Integer> maxComparator = (x, y) -> Integer.compare(y, x); // "y, x", did a fast flip! PriorityQueue<Integer> maxPQ = new PriorityQueue<>(maxComparator);

Here, we used our mathematical magician lambda expression, Integer.compare(y, x) to flip the comparison process. Remember, while pulling a rabbit out of the hat, beware of integer overflow. Alternately, use Comparator.reverseOrder() for built-in types.

Play nice with custom types

For custom types, apply the same logic. Design a comparator to determine the max order:

// assuming getValue() returns an int... Comparator<MyObject> maxComparator = (o1, o2) -> o2.getValue() - o1.getValue(); PriorityQueue<MyObject> maxPQ = new PriorityQueue<>(maxComparator);

With our trick o2.getValue() - o1.getValue(), the highest-value object always gets the top spot!

Common traps and tricky corners

Integer overflow: Our numeric nemesis

Whenever we define a comparator, we risk an integer overflow. Safeguard with Integer.compare() or write foolproof logic:

PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a, b) -> { if (a > b) return -1; // "a, you're a mountain!" if (a.equals(b)) return 0; // "a & b, you're mountain twins!" return 1; // "a, sorry but you're just a hill..." });

Handshake with complex objects

PriorityQueue requires a consistent comparator logic. And, when complex objects are part of this, ensure comparators can handle scary nulls and maintain type safety:

Comparator<MyObject> myObjectComparator = Comparator.comparing(MyObject::getKey, Comparator.nullsLast(Comparator.naturalOrder())).reversed();

The Comparator.comparing() and Comparator.nullsLast() combo help us maintain a null-safe comparison. Also, flipping the order with .reversed() gives us our desired max priority queue.

What if objects change?

Mutable objects in the PriorityQueue may affect ordering. Remember to remove, update, and reinsert elements whenever you mutate them.

Cool tricks with Java 8

Java 8 offers several static and default methods that can make your life with Comparator a lot easier. Try Comparator.comparing(), Comparator.thenComparing(), and Comparator.reverseOrder():

// So elegant. So simple. PriorityQueue<MyObject> maxPQ = new PriorityQueue<>(Comparator.comparing(MyObject::getValue).reversed());

Wonders of max priority queues

Max priority queues can go beyond sorting things. They can be used in scheduling tasks according to their importance, or to execute a greedy algorithm. You can even design a user preference sorting system. Happy exploring!