Ce face Collectors.minBy
minBy(comparator) și maxBy(comparator) aleg elementul minim, respectiv maxim, după regula din Comparator, de exemplu Comparator.comparingInt(Student::nota). Rezultatul este un Optional, gol dacă nu există elemente.
Pentru tot stream-ul, stream.min(...) și stream.max(...) sunt mai scurte. minBy/maxBy se folosesc în groupingBy: „cel mai bun student din fiecare grupă”. Dacă vrei valoarea fără Optional, învelește colectorul în collectingAndThen(..., Optional::orElseThrow).
Parametri
| Parametru | Descriere |
|---|---|
comparator |
Regula de comparare a elementelor. |
Ce returnează
Un Collector care produce un Optional<T> cu elementul găsit.
Exemple
Exemplul 1: Cel mai bun student din fiecare grupă
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class Main {
record Student(String nume, int grupa, int nota) {}
public static void main(String[] args) {
List<Student> studenti = List.of(
new Student("Ana", 101, 9), new Student("Radu", 101, 10),
new Student("Ioana", 102, 8), new Student("Dan", 102, 6));
Map<Integer, Optional<Student>> ceiMaiBuni = studenti.stream()
.collect(Collectors.groupingBy(Student::grupa, TreeMap::new,
Collectors.maxBy(Comparator.comparingInt(Student::nota))));
ceiMaiBuni.forEach((g, s) -> System.out.println(g + ": " + s.map(Student::nume).orElse("-")));
}
}
Rezultat
101: Radu
102: Ioana
Exemplul 2: Cel mai ieftin produs, fără Optional în rezultat
collectingAndThen aplică o funcție după colectare; aici scoate valoarea din Optional.
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class Main {
record Produs(String nume, String raion, int pret) {}
public static void main(String[] args) {
List<Produs> produse = List.of(
new Produs("mere", "fructe", 6), new Produs("banane", "fructe", 8),
new Produs("lapte", "lactate", 9), new Produs("iaurt", "lactate", 4));
Map<String, String> ieftine = produse.stream()
.collect(Collectors.groupingBy(Produs::raion, TreeMap::new,
Collectors.collectingAndThen(
Collectors.minBy(Comparator.comparingInt(Produs::pret)),
p -> p.map(Produs::nume).orElseThrow())));
System.out.println(ieftine);
Optional<Produs> scump = produse.stream().collect(Collectors.maxBy(Comparator.comparingInt(Produs::pret)));
System.out.println("Cel mai scump: " + scump.orElseThrow().nume());
}
}
Rezultat
{fructe=mere, lactate=iaurt}
Cel mai scump: lapte
Greșeli frecvente
- Te aștepți ca la egalitate să primești toate elementele.
minBy/maxBydau unul singur; pentru toți, grupează după notă și ia grupul maxim. - Apelezi
get()peOptionalfără verificare. ÎngroupingBygrupurile nu sunt goale, dar pe un stream golOptionaleste gol.
Comenzi înrudite
Stream.min / Stream.max: Găsesc cel mai mic și cel mai mare element după un Comparator; rezultatul este un Optional.Collectors.groupingBy: Împarte elementele în grupuri după o cheie (oraș, grupă, prima literă) și dă un Map cheie → listă sau cheie → rezultat.Collectors.teeing: Trimite fiecare element la doi colectori deodată și unește cele două rezultate cu o funcție, într-o singură parcurgere.IntStream.max: Returnează cel mai mare (max) sau cel mai mic (min) număr din IntStream, ca OptionalInt.