8 Essential Java Stream APIs to Simplify Collection Processing
This article introduces eight ready‑to‑use Java Stream APIs—including Stream.ofNullable, Stream.iterate, collectingAndThen, dropWhile/takeWhile, IntStream, teeing, concat, and partitioningBy—showing how each can cleanly handle nulls, generate sequences, transform collections, and combine streams with concise code examples.
1. Quickly filter null values: Stream.ofNullable
The Java 9 method Stream.ofNullable filters out null elements in a collection, helping avoid NullPointerExceptions.
List<String> names = Arrays.asList("Alice", null, "Bob", null, "Charlie");
List<String> nonNullNames = names.stream()
.flatMap(Stream::ofNullable)
.collect(Collectors.toList());
System.out.println(nonNullNames);Output:
[Alice, Bob, Charlie]2. Stream iteration: Stream.iterate()
Stream.iteratecreates an infinite sequence from a seed and a unary function.
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(e -> System.out.println(e));Output: 0 2 4 6 8 10 12 14 16 18
Note: Because Stream.iterate() generates an infinite stream, you should define a termination condition such as limit , findFirst , or findAny to avoid endless loops.
3. Collection transformation: collectingAndThen()
Introduced in Java 8, collectingAndThen applies a finishing transformation to the result of another collector.
List<String> fruits = Arrays.asList("apple", "banana", "orange");
Map<Integer, String> result = fruits.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(fruits::indexOf, String::toUpperCase),
Collections::unmodifiableMap));
System.out.println(result);Output:
{0=APPLE, 1=BANANA, 2=ORANGE}4. Drop and take while: dropWhile() & takeWhile()
Both methods, added in Java 9, process streams sequentially based on a predicate. takeWhile(): returns elements while the predicate holds. dropWhile(): discards elements while the predicate holds.
List<Integer> numbers = List.of(1,2,3,4,5,6,7);
numbers.stream()
.dropWhile(n -> n < 3)
.takeWhile(n -> n < 6)
.forEach(System.out::println);Output: 3 4 5
5. Integer streams: IntStream
Java 8 introduced IntStream with two common factories: IntStream.range() – excludes the end value. IntStream.rangeClosed() – includes the end value.
IntStream.range(1,5).forEach(System.out::println); // 1 2 3 4
IntStream.rangeClosed(1,5).forEach(System.out::println); // 1 2 3 4 56. Apply multiple collectors: teeing()
Java 12 added teeing to combine two collectors on the same stream.
Stream<Integer> nums = Stream.of(1,2,3,4);
Map<String, Integer> collect = nums.collect(Collectors.teeing(
Collectors.maxBy(Integer::compareTo),
Collectors.minBy(Integer::compareTo),
(e1, e2) -> Map.of("min", e1.get(), "max", e2.get())
));
System.out.println(collect);Output:
{max=4, min=1}7. Merge streams: Stream.concat()
Stream.concatjoins two streams into one.
Stream<Integer> stream1 = Stream.of(1,2,3);
Stream<Integer> stream2 = Stream.of(4,5,6);
Stream.concat(stream1, stream2).forEach(System.out::println);Output: 1 2 3 4 5 6
8. Partitioning: Collectors.partitioningBy
partitioningBysplits a stream into two groups based on a predicate.
Map<Boolean, List<String>> result1 = Stream.of("apple","banana","orange","grape")
.collect(Collectors.partitioningBy(f -> f.length() > 5));
System.out.println(result1);Output:
{false=[apple, grape], true=[banana, orange]}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
