Course – Black Friday 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Partner – Orkes – NPI EA (cat=Java)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – Black Friday 2025 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

1. Overview

The PriorityQueue is one of the most powerful data structures. It’s uncommon in enterprise applications, but we often use it for coding challenges and algorithm implementations.

In this tutorial, we’ll learn how to use Comparators with PriorityQueues and how to change the sorting order in such queues. We’ll then check a more generalized example with a custom class and how we can apply similar logic to a Pair class.

For the Pair class, we’ll use the implementation from Apache Commons. However, numerous options are available, and we can choose the one that best suits our needs.

2. PriorityQueue

First, let’s discuss the data structure itself. This structure’s main superpower is that it maintains the order of the elements while pushing them into the queue.

However, like other queues, it doesn’t provide an API to access the elements inside. We can only access the element in the front of the queue.

At the same time, we have several methods to remove elements from the queue: removeAt() and removeEq(). We can also use a couple of methods from the AbstractCollection. While helpful, they don’t provide random access to the elements.

3. Order

As was mentioned previously, the main feature of the PriorityQueue is that it maintains an order of elements. Unlike LIFO/FIFO, the order doesn’t depend on the order of insertions.

Thus, we should have a general idea of the order of the elements in the queue. We can use it with Comparable elements or provide a custom Comparator while creating a queue.

Because we have these two options, the parametrization doesn’t require the elements to implement the Comparable interface. Let’s check the following class:

public class Book {
    private final String author;
    private final String title;
    private final int publicationYear;

    // constuctor and getters
}

Parametrizing a queue with non-comparable objects is incorrect but won’t result in exceptions:

@ParameterizedTest
@MethodSource("bookProvider")
void givenBooks_whenUsePriorityQueueWithoutComparatorWithoutAddingElements_thenNoExcetption(List<Book> books) {
    PriorityQueue<Book> queue = new PriorityQueue<>();
    assertThat(queue).isNotNull();
}

At the same time, if we try to push such elements into the queue, it won’t be able to identify their natural order and throw ClassCastException:

@ParameterizedTest
@MethodSource("bookProvider")
void givenBooks_whenUsePriorityQueueWithoutComparator_thenThrowClassCastExcetption(List<Book> books) {
    PriorityQueue<Book> queue = new PriorityQueue<>();
    assertThatExceptionOfType(ClassCastException.class).isThrownBy(() -> queue.addAll(books));
}

This is a usual approach for such cases. Collections.sort() behaves similarly while attempting to sort non-comparable elements. We should consider this, as it won’t issue any compile-time errors.

4. Comparator

As was mentioned previously, we can identify the order of the queue in two different ways: implement the Comparable interface or provide a Comparator while initializing a queue.

4.1. Comparable Interface

The Comparable interface is useful when the elements have the idea of natural ordering, and we don’t need to provide it explicitly for our queue. Let’s take the example of the Meeting class:

public class Meeting implements Comparable {
    private final LocalDateTime startTime;
    private final LocalDateTime endTime;  
    private final String title;

    // constructor, getters, equals, and hashCode

    @Override
    public int compareTo(Meeting meeting) {
        return this.startTime.compareTo(meeting.startTime);
    }
}

In this case, the general order would be the starting time of a meeting. This isn’t a strict requirement, and different domains can have different ideas of natural order, but it’s good enough for our example.

We can use the Meeting class directly without additional work from our side:

@Test
void givenMeetings_whenUseWithPriorityQueue_thenSortByStartDateTime() {
    Meeting projectDiscussion = new Meeting(
      LocalDateTime.parse("2025-11-10T19:00:00"),
      LocalDateTime.parse("2025-11-10T20:00:00"),
      "Project Discussion"
    );
    Meeting businessMeeting = new Meeting(
      LocalDateTime.parse("2025-11-15T14:00:00"),
      LocalDateTime.parse("2025-11-15T16:00:00"),
      "Business Meeting"
    );
    PriorityQueue<Meeting> meetings = new PriorityQueue<>();
    meetings.add(projectDiscussion);
    meetings.add(businessMeeting);

    assertThat(meetings.poll()).isEqualTo(projectDiscussion);
    assertThat(meetings.poll()).isEqualTo(businessMeeting);
}

However, if we need to diverge from the default ordering, we should provide a custom Comparator.

4.2. Comparator

While creating a new PriorityQueue, we can pass a Comparator to the constructor and identify the order we want to use. Let’s take the Book class as an example. It created issues previously as it doesn’t implement the Comparable interface or provide no natural ordering.

Imagine we want to order our books by the year to create a reading list. We want to read older ones first to get more insight into the development of science fiction ideas and also understand the influences of the previously published books:

@ParameterizedTest
@MethodSource("bookProvider")
void givenBooks_whenUsePriorityQueue_thenSortThemBySecondElement(List<Book> books) {
    PriorityQueue<Book> queue = new PriorityQueue<>(Comparator.comparingInt(Book::getPublicationYear));
    queue.addAll(books);
    Book previousBook = queue.poll();
    while (!queue.isEmpty()) {
        Book currentBook = queue.poll();
        assertThat(previousBook.getPublicationYear())
          .isLessThanOrEqualTo(currentBook.getPublicationYear());
        previousBook = currentBook;
    }
}

Here, we use the method reference to create a comparator that would sort the books by year. We can add books to our reading queue and pick older books first.

5. Pair

After checking the examples with custom classes, using Pairs with a PriorityQueue is a trivial task. In general, there’s no difference in usage. Let’s consider that our Pairs contain the title and the year of publishing:

@ParameterizedTest
@MethodSource("pairProvider")
void givenPairs_whenUsePriorityQueue_thenSortThemBySecondElement(List<Pair<String, Integer>> pairs) {
    PriorityQueue<Pair<String, Integer>> queue = new PriorityQueue<>(Comparator.comparingInt(Pair::getSecond));

    queue.addAll(pairs);
    Pair<String, Integer> previousEntry = queue.poll();
    while (!queue.isEmpty()) {
        Pair<String, Integer> currentEntry = queue.poll();
        assertThat(previousEntry.getSecond()).isLessThanOrEqualTo(currentEntry.getSecond());
        previousEntry = currentEntry;
    }
}

As we can see, the last two examples are virtually identical. The only difference is that our Comparator uses the Pair class. For this example, we used Pair implementation from Apache Commons. However, there are a bunch of other options.

Also, we can use Map.Entry if none other options are available in our codebase or we don’t want to add new dependencies:

@ParameterizedTest
@MethodSource("mapEntryProvider")
void givenMapEntries_whenUsePriorityQueue_thenSortThemBySecondElement(List<Map.Entry<String, Integer>> pairs) {
    PriorityQueue<Map.Entry<String, Integer>> queue = new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));

    queue.addAll(pairs);
    Map.Entry<String, Integer> previousEntry = queue.poll();
    while (!queue.isEmpty()) {
        Map.Entry<String, Integer> currentEntry = queue.poll();
        assertThat(previousEntry.getValue()).isLessThanOrEqualTo(currentEntry.getValue());
        previousEntry = currentEntry;
    }
}

At the same time, we can easily create a new class to represent a pair. Optionally, we can use an array or a List parametrized by Object, but it’s not recommended as this breaks the type safety.

The combination of a Pair and a PriorityQueue is quite common for graph traversal algorithms, such as Dijkstra’s. Other languages, like JavaScript and Python, can create data structures on the fly. In contrast, Java requires some initial setup with additional classes or interfaces.

6. Conclusion

The PriorityQueue is an excellent data structure to implement more performant and straightforward algorithms. It allows customization with Comparators so that we can provide any sorting rules based on our domain requirements.

Combining PriorityQueue and Pairs helps us write more robust and easy-to-understand code. However, it’s often considered a more advanced data structure, and not all developers are fluent with its API.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Course – Black Friday 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – Black Friday 2025 – NPI (All)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

eBook Jackson – NPI EA – 3 (cat = Jackson)