Mastering Java’s Collectors.teeing() with Practical Examples

Learner, Love to make things simple, Full Stack Developer, StackOverflower, Passionate about using machine learning, deep learning and AI
Search for a command to run...

Learner, Love to make things simple, Full Stack Developer, StackOverflower, Passionate about using machine learning, deep learning and AI
No comments yet. Be the first to comment.
Move beyond traditional RESTful thinking. Learn how to design APIs specifically for MCP (Model Context Protocol) servers. This guide covers the shift in mindset, a practical OpenAPI 3.1 example, and a Spring Boot implementation to make your services ...

Extending Kestra to Every Corner of Your Data Stack. Introduction: The Power of Plugins Imagine you're a master chef. You don't just have one knife - you have specialized tools for every task: a paring knife for delicate work, a chef's knife for chop...
Mastering Complex Orchestration Scenarios. Introduction: The Orchestrator's Toolkit Imagine you're conducting a symphony. You don't just wave your baton - you cue sections, adjust tempo, handle surprises, and ensure harmony. That's what advanced work...
From Data Extraction to Loading - A Practical Guide Introduction: Why ETL Still Matters in the Modern Data Stack Remember when data engineering was "extract, transform, load"? Some say ETL is dead, replaced by ELT, reverse ETL, and data mesh. But her...
Building Blocks of Declarative Orchestration. Introduction: The Power of Simplicity Imagine trying to build a house without understanding bricks, beams, and blueprints. That's what using an orchestration tool without understanding its core concepts f...
Collectors.teeing()Java 12 introduced the Collectors.teeing() method, which allows developers to process a stream in two separate ways simultaneously, then merge the results with a BiFunction. This powerful collector is especially useful when you need to aggregate data or calculate multiple values from a single stream pass.
The Collectors.teeing() method takes three arguments:
Collector1 - the first collector for partial data processing.
Collector2 - the second collector for partial data processing.
Merger - a BiFunction that combines the results of both collectors into a final output.
Here's the basic syntax:
Stream<T> stream = ...;
Collector<T, ?, R> result = stream.collect(Collectors.teeing(
Collector1,
Collector2,
(result1, result2) -> mergeFunction(result1, result2)
));
Let’s say you have a list of product prices, and you want to calculate both the average and the total price in a single operation.
import java.util.List;
import java.util.stream.Collectors;
public class TeeingExample {
public static void main(String[] args) {
List<Double> prices = List.of(19.99, 9.99, 14.99, 29.99, 24.99);
var result = prices.stream().collect(Collectors.teeing(
Collectors.averagingDouble(Double::doubleValue),
Collectors.summingDouble(Double::doubleValue),
(average, sum) -> "Average Price: " + average + ", Total Price: " + sum
));
System.out.println(result); // Output: Average Price: 19.19, Total Price: 99.95
}
}
In this example:
Collector1 computes the average price.
Collector2 calculates the sum of prices.
Merger combines the average and total into a descriptive string.
For lists where you need the longest and shortest strings simultaneously, Collectors.teeing() can be handy.
import java.util.List;
import java.util.Comparator;
import java.util.stream.Collectors;
public class TeeingStringExample {
public static void main(String[] args) {
List<String> words = List.of("stream", "collector", "Java", "teeing", "example");
var result = words.stream().collect(Collectors.teeing(
Collectors.maxBy(Comparator.comparingInt(String::length)),
Collectors.minBy(Comparator.comparingInt(String::length)),
(longest, shortest) -> "Longest: " + longest.orElse("N/A") + ", Shortest: " + shortest.orElse("N/A")
));
System.out.println(result); // Output: Longest: collector, Shortest: Java
}
}
Here:
Collector1 finds the longest string.
Collector2 finds the shortest string.
Merger formats the output to display both results together.
Imagine you have a list of students with scores, and you want to count how many passed and failed based on a passing threshold.
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Student {
String name;
int score;
Student(String name, int score) {
this.name = name;
this.score = score;
}
public int getScore() {
return score;
}
}
public class TeeingCountExample {
public static void main(String[] args) {
List<Student> students = List.of(
new Student("Alice", 75),
new Student("Bob", 45),
new Student("Charlie", 85),
new Student("Daisy", 55)
);
Map<String, Long> result = students.stream().collect(Collectors.teeing(
Collectors.filtering(s -> s.getScore() >= 60, Collectors.counting()),
Collectors.filtering(s -> s.getScore() < 60, Collectors.counting()),
(passed, failed) -> Map.of("Passed", passed, "Failed", failed)
));
System.out.println(result); // Output: {Passed=2, Failed=2}
}
}
Explanation:
Collector1 filters and counts students who passed (score >= 60).
Collector2 filters and counts students who failed (score < 60).
Merger maps the counts to labels "Passed" and "Failed."
Collectors.teeing()Collectors.teeing() is useful when:
You need multiple results from a single stream processing pass.
You’re aggregating different calculations (e.g., count, sum, average) at once.
You’re merging multiple conditions or classifications from a stream.
Java 12+ Required: Collectors.teeing() is available only from Java 12 onwards.
Performance: While efficient for combined processing, complex operations may need careful testing for performance impacts on large data sets.
Alternative Approaches: For more than two collectors, consider multiple .collect() calls or switch to a Map.
Collectors.teeing() is a powerful tool for combining results of two distinct collectors into one operation. It’s perfect for scenarios where you want to optimize performance by reducing the number of passes over the stream. By mastering collectors teeing(), you can make your Java code cleaner and more efficient when handling multiple results from the same data source.
More such articles:
https://www.youtube.com/@maheshwarligade