Transform, Combine, and Reduce Data

Author      Ter-Petrosyan Hakob

Streams are a powerful way to work with data in Java. You can take parts of a stream, combine streams, remove duplicates, sort elements, or calculate results. Let’s see how.

Extracting Parts of a Stream

If you only need a certain number of elements from a stream, use limit. This is very useful with streams that could go on forever.

Stream<Integer> numbers = Stream.iterate(1, n -> n + 1).limit(50);

This stream now contains numbers from 1 to 50.

Sometimes, you want to ignore the first few elements.

Stream<String> words = Stream.of("","apple","banana","cherry").skip(1);
words.forEach(System.out::println);

Output:

apple
banana
cherry

You can take elements until a rule becomes false.

Stream<Integer> digits = Stream.of(1,2,3,0,4,5).takeWhile(n -> n != 0);
digits.forEach(System.out::println);

Output:

1
2
3

Opposite of takeWhile: skip elements until the condition is false.

Stream<String> fruits = Stream.of(""," ","apple","banana");
Stream<String> clean = fruits.dropWhile(s -> s.isBlank());
clean.forEach(System.out::println);

Output:

apple
banana

You can merge two streams into one.

Stream<String> letters = Stream.concat(Stream.of("A","B"), Stream.of("C","D"));

letters.forEach(System.out::println);

Output:

A
B
C
D

Other Transformations

distinct() – Remove duplicate elements

Stream<String> unique = Stream.of("apple","apple","banana").distinct();
unique.forEach(System.out::println);

Output:

apple
banana

You can sort elements alphabetically or with custom rules.

List<String> words = List.of("cat","elephant","dog");
Stream<String> longestFirst = words.stream()
   .sorted(Comparator.comparing(String::length)
   .reversed());

longestFirst.forEach(System.out::println);

Output:

elephant
cat
dog

Peek lets you see elements while the stream is processed.

Stream<Integer> powers = Stream.iterate(1, n -> n * 2)
   .peek(n -> System.out.println("Processing " + n))
   .limit(5);
powers.forEach(n -> {});

Output:

Processing 1
Processing 2
Processing 4
Processing 8
Processing 16

Simple Reductions

Reductions are terminal operations that return a single value from a stream.

count() – Count elements

long total = Stream.of("apple","banana","cherry").count();

max() and min() – Find largest or smallest

These return an Optional<T>, which is safer than returning null.

Optional<String> largest = Stream.of("apple","banana","cherry").max(String::compareToIgnoreCase);
System.out.println(largest.orElse("No words"));

findFirst() and findAny() – Find elements

Optional<String> first = Stream.of("apple","banana","cherry")
                               .filter(s -> s.startsWith("b"))
                               .findFirst();
System.out.println(first.orElse("No match"));

findAny() is useful in parallel streams when you don’t care which match is returned.


Match checks: anyMatch, allMatch, noneMatch

Stream<String> words = Stream.of("apple","banana","cherry");

// Check if any word starts with "b"
boolean anyB = words.anyMatch(s -> s.startsWith("b"));
System.out.println(anyB); // true