Java Tutorial

Java Control Statements

Object Oriented Programming

Java Built-in Classes

Java File Handling

Java Error & Exceptions

Java Multithreading

Java Synchronization

Java Networking

Java Collections

Java List Interface

Java Queue Interface

Java Map Interface

Java Set Interface

Java Data Structures

Java Collections Algorithms

Java Miscellaneous

Advanced Java

Java APIs & Frameworks

Java Useful Resources

Java - Teeing Collectors



Java Collectors.teeing() Method

Java 12 introduced a new static method to Collectors interface which can perform two different operations on collection and then merge the result.

Syntax

Following is the syntax of teeing method −

public static Collector<T, ?, R> teeing(
   Collector<? super T, ?, R1> downstream1,
   Collector<? super T, ?, R2> downstream2, 
   BiFunction<? super R1, ? super R2, R> merger
)

Here each element of the collection passed to the teeing collector is processed by downstream1 and downstream2 collectors, once the processing is completed by both the collectors, the results are passed to the BiFunction collector to merge the result or process accordingly. It is similar to calling two functions on a collection and then calling the third function to process the results of first two functions.

Here we are performing different functions on a collection and then merge the result using merger BiFunction.

Example - Using teeing collectors to get mean of n numbers

In this example, we're getting sum of numbers in downstream1 collector, count of numbers in downstream2 collector and then computing mean in the merger function. This is useful when we're getting a stream of numbers and size of stream is not available.

package com.tutorialspoint;

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

public class Tester {
   public static void main(String[] args) {
      double mean
         = Stream.of(1, 2, 3, 4, 5, 6, 7)
            .collect(Collectors.teeing(
               Collectors.summingDouble(i -> i), Collectors.counting(),
               (sum, n) -> sum / n));

      System.out.println(mean);
   }
}

Output

Let us compile and run the above program, this will produce the following result −

4.0

Example - Using teeing collectors to get lowest and highest marks of student objects

In this example, we're getting lowest marks of students in downstream1 collector and highest marks of students in downstream2 collector. Then using merger function, we're creating a hashmap with entry of student having lowest and highest marks.

package com.tutorialspoint;

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<Student> students = Arrays.asList(
         new Student(1, "Robert", 390),
         new Student(2, "Julie", 410),
         new Student(3, "John", 440),
         new Student(4, "Michael", 420));

      // collect the result in hashmap
      HashMap<String, Student> result = students.stream().collect(
      // apply the teeing operator
      Collectors.teeing(
         // get the student having highest marks
         Collectors.maxBy(Comparator.comparing(Student::getMarks)),
         // get the student having lowest marks
         Collectors.minBy(Comparator.comparing(Student::getMarks)),
         // put both student entries in the map using merger
         (s1, s2) -> {
            HashMap<String, Student> 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 void setRollNo(int rollNo) {
      this.rollNo = rollNo;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getMarks() {
      return marks;
   }

   public void setMarks(int marks) {
      this.marks = marks;
   }
}

Output

Let us compile and run the above program, this will produce the following result −

{Lowest=Student [RollNo=1, Name=Robert, Marks=390], Highest=Student [RollNo=3, Name=John, Marks=440]}
Advertisements