Collectors.teeing în Java

Trimite fiecare element la doi colectori deodată și unește cele două rezultate cu o funcție, într-o singură parcurgere.

Sintaxă
static <T, R1, R2, R> Collector<T, ?, R> teeing(Collector<T, ?, R1> primul,
        Collector<T, ?, R2> alDoilea, BiFunction<R1, R2, R> combinare)

Ce face Collectors.teeing

teeing (de la piesa în formă de T a instalatorilor) dă fiecare element la doi colectori diferiți, apoi combină cele două rezultate. Așa calculezi, de exemplu, minimul și maximul sau suma și numărul într-o singură trecere prin date.

Al treilea argument este o BiFunction care primește rezultatul primului colector și pe al celui de-al doilea și returnează rezultatul final, de exemplu un record sau un text.

Parametri

Parametru Descriere
primul Primul colector.
alDoilea Al doilea colector.
combinare Funcția care unește cele două rezultate.

Ce returnează

Un Collector care produce rezultatul funcției de combinare.

Exemple

Exemplul 1: Cea mai mică și cea mai mare temperatură

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

public class Main {
    record Interval(int minim, int maxim) {}

    public static void main(String[] args) {
        List<Integer> temperaturi = List.of(12, 18, 9, 21, 15);

        Interval interval = temperaturi.stream().collect(Collectors.teeing(
                Collectors.minBy(Comparator.<Integer>naturalOrder()),
                Collectors.maxBy(Comparator.<Integer>naturalOrder()),
                (min, max) -> new Interval(min.orElseThrow(), max.orElseThrow())));
        System.out.println(interval);
    }
}

Rezultat

Interval[minim=9, maxim=21]

Exemplul 2: Media calculată din sumă și număr

Un colector adună prețurile, celălalt le numără; funcția finală le împarte.

import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> preturi = List.of(25, 40, 15, 60);

        String raport = preturi.stream().collect(Collectors.teeing(
                Collectors.summingInt(p -> p),
                Collectors.counting(),
                (suma, cate) -> cate + " produse, total " + suma + " lei, medie " + suma / cate + " lei"));
        System.out.println(raport);
    }
}

Rezultat

4 produse, total 140 lei, medie 35 lei

Greșeli frecvente

  • Parcurgi lista de două ori (o dată pentru minim, o dată pentru maxim) când datele vin dintr-un stream care nu se poate relua, de exemplu dintr-un fișier. teeing rezolvă totul într-o trecere.
  • Folosești teeing doar pentru minim, maxim, sumă și medie la numere. IntStream.summaryStatistics() le dă pe toate deodată.

Comenzi înrudite

  • Collectors.minBy: Găsește elementul cel mai mic (minBy) sau cel mai mare (maxBy) după un Comparator; util pe grupuri, cu groupingBy.
  • Collectors.counting: Numără elementele; folosit mai ales în groupingBy, pentru „câte elemente are fiecare grup”.
  • BiFunction: O funcție cu doi parametri (de tipuri T și U) care returnează un R; o apelezi cu apply(a, b).
  • IntStream.summaryStatistics: Calculează într-o singură trecere numărul, suma, minimul, maximul și media numerelor din IntStream.