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 – 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 – 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 – 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 – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Browser testing is essential if you have a website or web applications that users interact with. Manual testing can be very helpful to an extent, but given the multiple browsers available, not to mention versions and operating system, testing everything manually becomes time-consuming and repetitive.

To help automate this process, Selenium is a popular choice for developers, as an open-source tool with a large and active community. What's more, we can further scale our automation testing by running on theLambdaTest cloud-based testing platform.

Read more through our step-by-step tutorial on how to set up Selenium tests with Java and run them on LambdaTest:

>> Automated Browser Testing With Selenium

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

eBook – Java Streams – NPI (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

1. Overview

In this article, we’ll explore how to find the maximal and minimal date in a list of those objects using Streams.

2. Example Setup

Java’s original Date API is still widely used, so we’ll showcase an example using it. However, since Java 8, LocalDate was introduced, and most Date methods were deprecated. Thus, we’ll also show an example that uses LocalDate.

Firstly, let’s create a base Event object that contains a lone Date property:

public class Event {

    Date date;

    // constructor, getter and setter
}

To add days to a Date, we’ll use Apache Commons’ DateUtils method addDays(). For that purpose, we need to add the latest version of the library to our pom.xml:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

We can now define a list of three Event: the first one taking place today, the second one tomorrow, and the third one in a week:

Date TODAY = new Date();
Event TODAYS_EVENT = new Event(TODAY);
Date TOMORROW = DateUtils.addDays(TODAY, 1);
Event TOMORROWS_EVENT = new Event(TOMORROW);
Date NEXT_WEEK = DateUtils.addDays(TODAY, 7);
Event NEXT_WEEK_EVENT = new Event(NEXT_WEEK);
List<Event> events = List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT);

Our goal is now to write a method that will be able to determine that NEXT_WEEK_EVENT is the maximal date in this Event list. We’ll also do the same with a LocalDate instead of a Date. Our LocalEvent will look like this:

public class LocalEvent {

    LocalDate date;

    // constructor, getter and setter
}

Building the Event list is a bit more straightforward since LocalDate already has a built-in plusDays() method:

LocalDate TODAY_LOCAL = LocalDate.now();
LocalEvent TODAY_LOCAL_EVENT = new LocalEvent(TODAY_LOCAL);
LocalDate TOMORROW_LOCAL = TODAY_LOCAL.plusDays(1);
LocalEvent TOMORROW_LOCAL_EVENT = new LocalEvent(TOMORROW_LOCAL);
LocalDate NEXT_WEEK_LOCAL = TODAY_LOCAL.plusWeeks(1);
LocalEvent NEXT_WEEK_LOCAL_EVENT = new LocalEvent(NEXT_WEEK_LOCAL);
List<LocalEvent> localEvents = List.of(TODAY_LOCAL_EVENT, TOMORROW_LOCAL_EVENT, NEXT_WEEK_LOCAL_EVENT);

3. Get the Max Date

To start, we’ll use the Stream API to stream our Event list. Then, we’ll need to apply the Date getter to each element of the Stream. Thus, we’ll obtain a Stream containing the dates of the events. We can now use the max() function for it. This will return the maximal Date in the Stream regarding the provided Comparator.

The Date class implements Comparable<Date>. As a result, the compareTo() method defines the natural date order. In a nutshell, it is possible to equivalently call the two following methods inside max():

  • Date‘s compareTo() can be referred to via a method reference
  • Comparator‘s naturalOrder() can be used directly

Lastly, let’s note that if the given Event list is null or empty, we can directly return null. This will ensure we don’t run into issues while streaming the list.

The method finally looks like this:

Date findMaxDateOf(List<Event> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return events.stream()
      .map(Event::getDate)
      .max(Date::compareTo)
      .get();
}

Alternatively, with naturalOrder(), it would read:

Date findMaxDateOf(List<Event> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return events.stream()
      .map(Event::getDate)
      .max(Comparator.naturalOrder())
      .get();
}

To conclude, we can now quickly test that our method returns the correct result for our list:

assertEquals(NEXT_WEEK, findMaxDateOf(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT);

With LocalDate, the reasoning is exactly the same. LocalDate indeed implements the ChronoLocalDate interface, which extends Comparable<ChronoLocalDate>. Thus, the natural order for LocalDate is defined by ChronoLocalDate‘s compareTo() method.

As a result, the method can be written:

LocalDate findMaxDateOf(List<LocalEvent> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return events.stream()
      .map(LocalEvent::getDate)
      .max(LocalDate::compareTo)
      .get();
}

Or, in a completely equivalent way:

LocalDate findMaxDateOf(List<LocalEvent> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return events.stream()
      .map(LocalEvent::getDate)
      .max(Comparator.naturalOrder())
      .get();
}

And we can write the following test to confirm it works:

assertEquals(NEXT_WEEK_LOCAL, findMaxDateOf(List.of(TODAY_LOCAL_EVENT, TOMORROW_LOCAL_EVENT, NEXT_WEEK_LOCAL_EVENT)));

4. Get the Max Date Using Collections.max()

Java’s Collections utility class provides a max() method, which can be used to find the maximum element in a collection. Let’s see how we can use Collections.max() to find the maximum date in our Event list:

Date findMaxDateWithCollections(List<Event> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return Collections.max(events.stream()
      .map(Event::getDate)
      .collect(Collectors.toList()));
}

In this method, we first map the list of Event objects to their corresponding Date values using map(). Next, we then collect these dates into a list and pass the result to Collections.max().

Let’s create a test to verify the functionality of the method:

assertEquals(NEXT_WEEK, findMaxDateWithCollections(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT)));

Similarly, we can use Collections.max() with the list of LocalEvent objects:

LocalDate findMaxLocalDateWithCollections(List<LocalEvent> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return Collections.max(events.stream()
      .map(LocalEvent::getDate)
      .collect(Collectors.toList()));
}

Here, the process is exactly the same, but using LocalDate instead of Date. Let’s create a test to verify the functionality of the method:

assertEquals(NEXT_WEEK_LOCAL, findMaxLocalDateWithCollections(List.of(TODAY_LOCAL_EVENT, TOMORROW_LOCAL_EVENT, NEXT_WEEK_LOCAL_EVENT)));

5. Get the Min Date

Similarly, we can find the minimal date in a Date list:

Date findMinDateOf(List<Event> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return events.stream()
      .map(Event::getDate)
      .min(Date::compareTo)
      .get();
}

As we can see, the only change is that we used the min() function instead of max(). Let’s verify it gives us the earliest date of the three:

@Test
void givenEventList_whenFindMinDateOf_thenReturnMinDate() {
    assertEquals(TODAY, DateHelper.findMinDateOf(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT)));
}

If we are working with LocalDate, we’ll use this method:

LocalDate findMaxDateOfLocalEvents(List<LocalEvent> events) {
    if (events == null || events.isEmpty()) {
        return null;
    }
    return events.stream()
      .map(LocalEvent::getDate)
      .max(LocalDate::compareTo)
      .get();
}

Once again, the only change we made is replacing the call to max() with a call to the min() method. Finally, we can also test it:

@Test
void givenEventList_whenFindMinDateOfWithComparator_thenReturnMaxDate() {
    assertEquals(TODAY, DateHelper.findMinDateOfWithComparator(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT)));
}

6. Conclusion

In this tutorial, we saw how to get the maximum or minimum date in a list of objects. We’ve used both Date and LocalDate objects.

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.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

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

eBook – Java Streams – NPI (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 – 3 (cat = Jackson)