BinaryOperator în Java

O funcție care combină două valori de același tip într-una (T, T → T); folosită de reduce, toMap și Map.merge.

Sintaxă
import java.util.function.BinaryOperator;

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T, T, T>
static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator)
static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator)

Ce face BinaryOperator

BinaryOperator<T> primește două valori de tip T și returnează tot un T. Exemple: adunarea (Integer::sum), maximul (Math::max), lipirea a două texte.

Este tipul cerut de Stream.reduce, de funcția de combinare din Collectors.toMap și de Map.merge. Metodele statice BinaryOperator.minBy(comparator) și maxBy(comparator) creează un operator care păstrează valoarea mai mică, respectiv mai mare.

Ce returnează

apply(a, b) returnează valoarea combinată, de tipul T.

Exemple

Exemplul 1: Operatori pentru reduce

import java.util.Comparator;
import java.util.List;
import java.util.function.BinaryOperator;

public class Main {
    public static void main(String[] args) {
        BinaryOperator<Integer> suma = Integer::sum;
        BinaryOperator<String> lipire = (a, b) -> a + "-" + b;
        BinaryOperator<String> maiLung = BinaryOperator.maxBy(Comparator.comparingInt(String::length));

        System.out.println(suma.apply(15, 27));
        System.out.println(List.of(9, 7, 10).stream().reduce(0, suma));
        System.out.println(List.of("Iași", "Vaslui", "Bacău").stream().reduce(lipire).orElse(""));
        System.out.println(List.of("Iași", "Vaslui", "Bacău").stream().reduce(maiLung).orElse(""));
    }
}

Rezultat

42
26
Iași-Vaslui-Bacău
Vaslui

Exemplul 2: Map.merge: numărarea voturilor

Când candidatul există deja, merge folosește operatorul ca să combine valoarea veche cu cea nouă.

import java.util.Map;
import java.util.TreeMap;
import java.util.function.BinaryOperator;

public class Main {
    public static void main(String[] args) {
        BinaryOperator<Integer> aduna = Integer::sum;
        Map<String, Integer> voturi = new TreeMap<>();
        for (String vot : new String[]{"Ana", "Radu", "Ana", "Ioana", "Ana", "Radu"}) {
            voturi.merge(vot, 1, aduna);
        }
        System.out.println(voturi);
    }
}

Rezultat

{Ana=3, Ioana=1, Radu=2}

Greșeli frecvente

  • Folosești în reduce paralel o operație care nu este asociativă (de exemplu scăderea): rezultatul depinde de ordinea împărțirii. Adunarea, maximul și lipirea sunt sigure.
  • Ai tipuri diferite pentru intrări sau rezultat. Atunci ai nevoie de BiFunction, nu de BinaryOperator.

Comenzi înrudite

  • BiFunction: O funcție cu doi parametri (de tipuri T și U) care returnează un R; o apelezi cu apply(a, b).
  • UnaryOperator: O Function în care intrarea și ieșirea au același tip (T → T); folosită de List.replaceAll și Stream.iterate.
  • Stream.reduce: Combină toate elementele într-o singură valoare, aplicând o operație pas cu pas (sumă, produs, maxim, concatenare).
  • 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ă.
  • Collectors.reducing: Varianta de colector a lui reduce: combină elementele două câte două; util ca downstream în groupingBy.