Backend Development 8 min read

Why List.sort() Is Faster Than Stream.sorted() in Java: Benchmarks and Analysis

This article investigates the performance difference between Java's List.sort() and Stream.sorted(), providing simple demos, JMH benchmark results, and analysis of underlying overheads to explain why the native list sorting is generally faster than sorting via streams.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Why List.sort() Is Faster Than Stream.sorted() in Java: Benchmarks and Analysis

The article revisits the claim that List.sort() outperforms Stream.sorted() by first presenting a simple demo that measures execution time for both methods on a list of 10,000 random integers.

List<Integer> userList = new ArrayList<>();
Random rand = new Random();
for (int i = 0; i < 10000 ; i++) {
    userList.add(rand.nextInt(1000));
}
List<Integer> userList2 = new ArrayList<>();
userList2.addAll(userList);
Long startTime1 = System.currentTimeMillis();
userList2.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());
System.out.println("stream.sort耗时:"+(System.currentTimeMillis() - startTime1)+"ms");
Long startTime = System.currentTimeMillis();
userList.sort(Comparator.comparing(Integer::intValue));
System.out.println("List.sort()耗时:"+(System.currentTimeMillis()-startTime)+"ms");

The first run shows List.sort() taking about 7 ms versus 62 ms for the stream version, suggesting the native sort is faster, but a second ordering of the calls reverses the results, demonstrating that such naive timing is unreliable.

To obtain reliable measurements the article introduces JMH (Java Microbenchmark Harness) and provides a benchmark class that tests both sorting approaches for collection sizes of 100, 10 000 and 100 000 elements.

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 2, time = 1)
@Measurement(iterations = 5, time = 5)
@Fork(1)
@State(Scope.Thread)
public class SortBenchmark {

    @Param(value = {"100", "10000", "100000"})
    private int operationSize;

    private static List<Integer> arrayList;

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(SortBenchmark.class.getSimpleName())
                .result("SortBenchmark.json")
                .mode(Mode.All)
                .resultFormat(ResultFormatType.JSON)
                .build();
        new Runner(opt).run();
    }

    @Setup
    public void init() {
        arrayList = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < operationSize; i++) {
            arrayList.add(random.nextInt(10000));
        }
    }

    @Benchmark
    public void sort(Blackhole blackhole) {
        arrayList.sort(Comparator.comparing(e -> e));
        blackhole.consume(arrayList);
    }

    @Benchmark
    public void streamSorted(Blackhole blackhole) {
        arrayList = arrayList.stream().sorted(Comparator.comparing(e -> e)).collect(Collectors.toList());
        blackhole.consume(arrayList);
    }
}

The benchmark results confirm that List.sort() consistently has lower average execution time than Stream.sorted() , although the difference shrinks for larger data sets.

The overhead stems from creating a stream, applying the sorting operation, and then collecting the elements back into a list; the native List.sort() directly sorts the underlying array without these extra steps. Additionally, JIT compilation and inlining affect timings, so proper warm‑up is essential.

In summary, while streams provide expressive and concise code, for pure list sorting the built‑in List.sort() is generally faster, and developers should use benchmarks like JMH rather than ad‑hoc timing when performance matters.

Note: the discussion concerns sequential streams; parallel streams have different characteristics.

JavaPerformanceBenchmarkJMHlist.sortStream.sorted
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.