Java Collectors.teeing() Method: Merging Results from Two Operations

Discover the teeing() method introduced in Java 12, a static method in the Collectors interface. Learn how it enables performing two different operations on a collection and merging their results in a streamlined way.



Java - Collectors.teeing() Method

Introduction

Java 12 introduced a new static method in the Collectors interface, called teeing(), which allows performing two different operations on a collection and then merging the results.

Syntax

Below is the syntax of the teeing method:

Syntax

public static Collector teeing(
    Collector downstream1,
    Collector downstream2, 
    BiFunction merger
)
        
Output

// Method Definition for Collectors.teeing
        

Each element of the collection passed to the teeing collector is processed by downstream1 and downstream2 collectors. Once processing is completed by both collectors, the results are passed to the merger function to be combined or processed accordingly. This is akin to calling two functions on a collection and then invoking a third function to process the results of the first two.

Example - Using teeing Collectors to Get Mean of n Numbers

In this example, we calculate the sum of numbers using downstream1 collector and the count of numbers using downstream2 collector, then compute the mean in the merger function. This is especially useful when dealing with a stream of numbers where the size of the stream is not readily available.

Example Code

package com.tutorialsarena;

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Tester {
    public static void main(String[] args) {
        double mean
            = Stream.of(5, 10, 15, 20, 25, 30, 35)
            .collect(Collectors.teeing(
                Collectors.summingDouble(i -> i), 
                Collectors.counting(),
                (sum, n) -> sum / n));

        System.out.println(mean);
    }
}
        
Output

20.0
        

Example - Using teeing Collectors to Get Lowest and Highest Marks of Student Objects

In this example, we will retrieve the lowest marks from students using downstream1 collector and the highest marks using downstream2 collector. The merger function will create a HashMap with entries for the students with the lowest and highest marks.

Example Code

package com.tutorialsarena;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

public class Tester {
    public static void main(String args[]) {
        // List of students
        List students = Arrays.asList(
            new Student(1, "Alice", 300),
            new Student(2, "Bob", 450),
            new Student(3, "Charlie", 500),
            new Student(4, "David", 400));

        // Collect the result in a HashMap
        HashMap result = students.stream().collect(
            Collectors.teeing(
            Collectors.maxBy(Comparator.comparing(Student::getMarks)),
            Collectors.minBy(Comparator.comparing(Student::getMarks)),
            (s1, s2) -> {
                HashMap map = new HashMap<>();
                map.put("Highest", s1.get());
                map.put("Lowest", s2.get());
                return map;
            }
            ));
        System.out.println(result);
    }
}

class Student {
    int rollNo;
    String name;
    int marks;

    public Student(int rollNo, String name, int marks) {
        this.rollNo = rollNo;
        this.name = name;
        this.marks = marks;
    }

    @Override
    public String toString() {
        return "Student [RollNo=" + rollNo + ", Name=" + name + ", Marks=" + marks + "]";
    }

    public int getRollNo() {
        return rollNo;
    }

    public String getName() {
        return name;
    }

    public int getMarks() {
        return marks;
    }
}
        
Output

{Lowest=Student [RollNo=1, Name=Alice, Marks=300], Highest=Student [RollNo=3, Name=Charlie, Marks=500]}