What is the best way to use a PriorityQueue in Java, and how can I customize its sorting using a comparator?

I’m trying to understand how to properly use a PriorityQueue in Java and how to make it sort elements based on my custom criteria. By default, it seems to sort elements in natural order, but what if I want to define my own sorting logic?

Also, while looking through the documentation, I noticed both the offer() and add() methods. Is there any difference between them, or are they interchangeable?

If you want to customize sorting without creating a separate class, you can use an anonymous comparator like this:

PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a); // Max-Heap
pq.add(10);
pq.add(20);
pq.add(5);

System.out.println(pq.poll()); // Outputs 20 (highest first)

Here, we override the default natural ordering using a lambda function. This turns it into a Max-Heap where the highest value comes out first.

If your PriorityQueue is working with complex objects, like a Person, defining a separate Comparator class makes things cleaner and reusable:

class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return Integer.compare(p1.age, p2.age); // Sort by age (ascending)
    }
}


// Usage:
PriorityQueue<Person> pq = new PriorityQueue<>(new AgeComparator());
pq.add(new Person("Alice", 30));
pq.add(new Person("Bob", 25));

System.out.println(pq.poll().name); // Outputs "Bob" (youngest first)

This makes the sorting logic reusable and improves readability.

If your class implements Comparable, or you use Comparator.comparing(), it simplifies things:

PriorityQueue<Person> pq = new PriorityQueue<>(Comparator.comparing(p -> p.age));

This sorts the PriorityQueue based on age in ascending order.