Skip to content

Streams

Performance Tips

Creating Streams in a Non-Optimal Way

Avoid creating a stream from a collection every time you need to process it. Instead, create it once and reuse it.

Avoid stateful operations

Stateful operations, such as sorted() or distinct(), can cause performance issues. So use them wisely.

Remove duplicates

If not explicitly required, remove duplicates.

java
List<String> systems = Arrays.asList("c64", "amiga", "amiga", "lynx");

List<String> uniqueItems = systems.stream()
                                  .distinct()
                                  .collect(Collectors.toList());
// Result: c64, amiga, lynx

Filter before map

java
List<String> systems = Arrays.asList("c64", "amiga", "lynx");
List<String> filteredList = list.stream()
                                .filter(s -> "lynx".compareTo(syste)!="lynx")
                                .map(String::toUpperCase)
                                .collect(Collectors.toList());

First remove all not important elements and only map the reduced entities

General Tips

Avoid Nullpointer Exceptions

You can avoid NPE by filtering them out.

java
List<String> filteredNames = list.stream()
                                 .flatMap(Stream::ofNullable)
                                 .collect(Collectors.toList());
java

List<String> filteredNames = list.stream()
                                 .filter(Objects::nonNull)
                                 .collect(Collectors.toList());

Sequence generator

java
Easy way to generate sequences.
Stream.iterate(1, n -> n + 3)
      .limit(6)
      .forEach(System.out::println);
// Result: 1, 4, 7, 10, 13, 16

Post processing of streams

You can process a stream, collect the result and made some post processing with collectAndThen

java
long carSales = cars.stream()
                    .collect(Collectors.collectingAndThen(
                      Collectors.averagingDouble(cars::getSalePrice),
                      Math::round));

takeWhile, dropWhile

With take while, dropWhile you can slice your collection. The difference to filter is, that filter will evaluate each member of the stream. takeWhile, dropWhile will abort the stream on the first occurrence of an item which does not satisfy the condition. So it can massivly improve the performance on sorted lists. But beware.

java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> taken = numbers.stream()
                             .takeWhile(n -> n < 5)
                             .collect(Collectors.toList());
// Result [1, 2, 3, 4]
java
List<Integer> numbers = List.of(1, 2, 6, 7, 8);
List<Integer> taken = numbers.stream()
                             .dropWhile(n -> n < 5)
                             .collect(Collectors.toList());
// Result [1, 2]

Collectors.teeing

The Collectors.teeing() method is useful when we want to simultaneously process a stream in two different ways and then combine their results. If not using the teeing() method, we would have processed the stream two times

java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8);

String result = numbers.stream().collect(
Collectors.teeing(
                  Collectors.averagingInt(Integer::intValue),
                  Collectors.summingInt(Integer::intValue),
                  (average, sum) -> String.format("Average: %.2f, Sum: %d", average, sum)
                 )
);

Contact: M_Bergmann AT gmx.at