Explain Codes LogoExplain Codes Logo

Sorting a list with stream.sorted() in Java

java
stream-api
sorting-algorithms
java-8
Nikita BarsukovbyNikita Barsukov·Mar 6, 2025
TLDR

Here's how you sort a list in a jiffy with Java's stream().sorted():

List<String> sorted = list.stream().sorted().collect(Collectors.toList());

Want a custom sort, for example, sorting in descending order? Just inject a Comparator:

List<String> sorted = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

Just don't forget to import Collectors.toList() and Comparator.reverseOrder().

In-depth explanation

Let's get our hands dirty and dive a bit deeper into the powerful Stream.sorted(). It's a stateful intermediate operation, so it's like a deck of cards, you have to know all the cards before you can sort them.

In-place vs. new list

stream().sorted() gives you a new sorted list, but if you want the original array modified, use list.sort():

// No more original unsorted list, you'll sorely miss it for sure list.sort(Comparator.naturalOrder());

This directly modifies the original list; discretion is advised! To keep your original list safe and untouched, remember to assign the sorted output to a new list.

Custom objects? No problem!

So your list is filled with custom objects and not just plain strings or integers? Simply tell Comparator.comparing() how to compare your objects:

List<Person> sortedPeople = people.stream() .sorted(Comparator.comparing(Person::getAge)) .collect(Collectors.toList());

Hey look, it's all sorted by age now!

The power of chaining

You can chain comparators if you can't decide on a single property to sort by using thenComparing():

List<Person> sortedPeople = people.stream() .sorted(Comparator.comparing(Person::getName) .thenComparingInt(Person::getAge)) .collect(Collectors.toList());

Look, we now have a fallback, it's like a polite tie-break in chess!

Pro tips and gotchas

Moving on to some imperative considerations and pro tips for putting stream().sorted() into effective use.

High precision sorting

When sorting BigDecimal and other high-precision numeric values, use suitable comparators:

// We're all about precision here, no approximate guesses! List<BigDecimal> sortedDecimals = decimals.stream() .sorted(Comparator.naturalOrder()) .collect(Collectors.toList());

The proof is in the pudding

Make sure your sort order is as expected. Unit tests can save your day, and reputation:

// When the dust settles, we'll see who's nailed it assertTrue(Ordering.natural().isOrdered(sortedList));

Simplified collection with JDK 16

Java 16 introduced toList(). Going collector-less is the new fad:

List<String> sorted = list.stream().sorted().toList();

Roll your own comparator

Lambda expressions in action for an explicit comparator:

Comparator<String> explicitComparator = (s1, s2) -> s1.compareTo(s2); // We don't conform, we make our own rules here! List<String> sorted = list.stream().sorted(explicitComparator).collect(Collectors.toList());

Before-and-after comparison

A side-by-side comparison to confirm and marvel at your sorting skills:

Old rowdy gang: 📦5️⃣ 📦3️⃣ 📦1️⃣ 📦4️⃣ 📦2️⃣ New orderly squad: 📦1️⃣ 📦2️⃣ 📦3️⃣ 📦4️⃣ 📦5️⃣

Get a load off your chest

Can't contain your excitement over the sorted list? Let it out:

// It's a party, print'em all! sorted.forEach(System.out::println);

Got your imports right?

Don't forget the essential imports:

// The usual suspects import java.util.Arrays; import java.util.stream.Collectors;