Ce face Collectors
Collectors este o clasă cu metode statice care returnează un Collector, adică o „rețetă” prin care stream.collect(...) adună elementele într-un rezultat: toList(), toSet(), toMap(...), joining(", "), groupingBy(...), counting() și altele.
Colectorii se pot combina: groupingBy și partitioningBy primesc un al doilea colector (numit downstream) care spune ce se întâmplă cu fiecare grup, de exemplu counting() sau averagingDouble(...). Așa obții într-o singură linie „numărul de studenți pe oraș” sau „media pe grupă”.
De obicei se scrie import static java.util.stream.Collectors.*; sau se folosește numele complet: Collectors.joining(). Pe paginile de mai jos folosim numele complet, ca să se vadă de unde vine fiecare metodă.
Ce returnează
Metodele clasei returnează obiecte Collector<T, A, R>, date mai departe lui Stream.collect.
Exemple
Exemplul 1: Același stream, colectori diferiți
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> orase = List.of("Iași", "Cluj", "Iași", "Brașov", "Cluj", "Arad");
System.out.println(orase.stream().collect(Collectors.toList()));
Set<String> sortate = orase.stream().collect(Collectors.toCollection(TreeSet::new));
System.out.println(sortate);
System.out.println(orase.stream().collect(Collectors.joining(", ")));
System.out.println(orase.stream().collect(Collectors.counting()));
}
}
Rezultat
[Iași, Cluj, Iași, Brașov, Cluj, Arad]
[Arad, Brașov, Cluj, Iași]
Iași, Cluj, Iași, Brașov, Cluj, Arad
6
Exemplul 2: Colectori combinați: câți studenți și ce medie are fiecare oraș
groupingBy împarte studenții pe orașe, iar colectorul al doilea calculează ceva pentru fiecare oraș. TreeMap::new ține orașele sortate.
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class Main {
record Student(String nume, String oras, double medie) {}
public static void main(String[] args) {
List<Student> studenti = List.of(
new Student("Ana", "Iași", 9.50), new Student("Radu", "Cluj", 8.00),
new Student("Ioana", "Iași", 7.50), new Student("Dan", "Cluj", 9.00),
new Student("Elena", "Arad", 10.00));
Map<String, Long> cati = studenti.stream()
.collect(Collectors.groupingBy(Student::oras, TreeMap::new, Collectors.counting()));
Map<String, Double> medii = studenti.stream()
.collect(Collectors.groupingBy(Student::oras, TreeMap::new, Collectors.averagingDouble(Student::medie)));
System.out.println("Studenți pe oraș: " + cati);
System.out.println("Media pe oraș: " + medii);
}
}
Rezultat
Studenți pe oraș: {Arad=1, Cluj=2, Iași=2}
Media pe oraș: {Arad=10.0, Cluj=8.5, Iași=8.5}
Greșeli frecvente
- Uiți importul
java.util.stream.Collectorsși primeșticannot find symbol. - Afișezi un map produs de
groupingBysautoMapși te bazezi pe ordinea cheilor. Este unHashMapfără ordine garantată; cere unTreeMap(vezigroupingBy). - Folosești
collect(Collectors.toList())din obișnuință. Din Java 16,stream.toList()este mai scurt (dar lista returnată nu se poate modifica).
Comenzi înrudite
Stream.collect: Adună elementele într-un rezultat (listă, set, map, text) folosind un Collector, de obicei din clasa Collectors.Collectors.toList: Adună elementele stream-ului într-o listă (toList), într-o mulțime fără duplicate (toSet) sau într-o listă ce nu se poate modifica.Collectors.groupingBy: Împarte elementele în grupuri după o cheie (oraș, grupă, prima literă) și dă un Map cheie → listă sau cheie → rezultat.Collectors.joining: Unește textele din stream într-un singur String, cu un separator și, opțional, un început și un sfârșit.Collectors.toMap: Construiește un Map din stream: o funcție dă cheia, alta valoarea; o a treia spune ce faci când cheia se repetă.