Ce face Collectors.reducing
reducing face același lucru ca Stream.reduce: pornește de la o valoare inițială (identitatea) și combină pe rând elementele cu o operație, de exemplu adunarea. Folosit direct, reduce este mai simplu.
Utilitatea apare în groupingBy: „cea mai lungă denumire pe categorie” sau „produsul notelor pe grupă”. Varianta cu trei argumente transformă întâi fiecare element cu f și abia apoi combină. Pentru sume, numărări și maxime există colectori dedicați, mai clari (summingInt, counting, maxBy).
Parametri
| Parametru | Descriere |
|---|---|
identitate |
Valoarea de pornire (0 pentru sumă, 1 pentru produs, „” pentru texte). |
f |
Opțional: transformarea aplicată fiecărui element înainte de combinare. |
op |
Operația care unește două valori într-una. |
Ce returnează
Un Collector cu rezultatul combinării (un Optional în varianta fără identitate).
Exemple
Exemplul 1: Cel mai lung nume de oraș din fiecare județ
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
public class Main {
record Localitate(String nume, String judet) {}
public static void main(String[] args) {
List<Localitate> lista = List.of(
new Localitate("Iași", "IS"), new Localitate("Pașcani", "IS"),
new Localitate("Hârlău", "IS"), new Localitate("Cluj-Napoca", "CJ"), new Localitate("Dej", "CJ"));
BinaryOperator<String> maiLung = (a, b) -> b.length() > a.length() ? b : a;
Map<String, String> rezultat = lista.stream()
.collect(Collectors.groupingBy(Localitate::judet, TreeMap::new,
Collectors.reducing("", Localitate::nume, maiLung)));
System.out.println(rezultat);
}
}
Rezultat
{CJ=Cluj-Napoca, IS=Pașcani}
Exemplul 2: reducing cu și fără identitate
Fără valoare inițială rezultatul este un Optional, gol pentru o listă goală.
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> zile = List.of(3, 5, 2);
int total = zile.stream().collect(Collectors.reducing(0, Integer::sum));
Optional<Integer> produs = zile.stream().collect(Collectors.reducing((a, b) -> a * b));
Optional<Integer> gol = List.<Integer>of().stream().collect(Collectors.reducing(Integer::sum));
System.out.println("Total zile de concediu: " + total);
System.out.println("Produs: " + produs.orElse(0));
System.out.println("Listă goală: " + gol);
}
}
Rezultat
Total zile de concediu: 10
Produs: 30
Listă goală: Optional.empty
Greșeli frecvente
- Dai o identitate greșită, de exemplu
1pentru o sumă: fiecare grup primește în plus valoarea inițială. - Folosești
reducingpentru sume sau numărări.summingIntșicountingse citesc mai ușor.
Comenzi înrudite
Stream.reduce: Combină toate elementele într-o singură valoare, aplicând o operație pas cu pas (sumă, produs, maxim, concatenare).Collectors.groupingBy: Împarte elementele în grupuri după o cheie (oraș, grupă, prima literă) și dă un Map cheie → listă sau cheie → rezultat.BinaryOperator: O funcție care combină două valori de același tip într-una (T, T → T); folosită de reduce, toMap și Map.merge.Collectors.minBy: Găsește elementul cel mai mic (minBy) sau cel mai mare (maxBy) după un Comparator; util pe grupuri, cu groupingBy.