Stream.mapMulti în Java

Pentru fiecare element trimiți zero, una sau mai multe valori mai departe, apelând consumer.accept(...).

Sintaxă
<R> Stream<R> mapMulti(BiConsumer<? super T, ? super Consumer<R>> f)
IntStream mapMultiToInt(BiConsumer<? super T, ? super IntConsumer> f)
LongStream mapMultiToLong(BiConsumer<? super T, ? super LongConsumer> f)
DoubleStream mapMultiToDouble(BiConsumer<? super T, ? super DoubleConsumer> f)

Ce face Stream.mapMulti

mapMulti face același lucru ca flatMap, dar fără să creezi un stream pentru fiecare element. Lambda primește elementul și un „consumator” (Consumer); fiecare apel consumator.accept(x) trimite valoarea x în stream-ul rezultat. Dacă nu apelezi niciodată accept, elementul dispare.

Este mai eficient decât flatMap când un element produce puține valori, și mai ușor de citit când logica are if-uri. Tipul rezultatului trebuie de obicei scris explicit: .<String>mapMulti(...).

mapMultiToInt, mapMultiToLong și mapMultiToDouble produc direct stream-uri de numere primitive, cu sum() și average().

Parametri

Parametru Descriere
f Funcția care primește elementul și consumatorul; apelează accept pentru fiecare valoare de trimis.

Ce returnează

Un stream cu toate valorile trimise prin accept, în ordinea apelurilor.

Exemple

Exemplul 1: Filtrare și transformare într-un singur pas

Numerele negative sunt eliminate, iar cele pare apar de două ori.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numere = List.of(3, -1, 4, 7, -5, 10);
        List<Integer> rezultat = numere.stream()
                .<Integer>mapMulti((n, trimite) -> {
                    if (n < 0) {
                        return;              // nimic trimis: elementul dispare
                    }
                    trimite.accept(n);
                    if (n % 2 == 0) {
                        trimite.accept(n);   // pare: încă o dată
                    }
                })
                .toList();
        System.out.println(rezultat);
    }
}

Rezultat

[3, 4, 4, 7, 10, 10]

Exemplul 2: Variante pentru numere primitive

import java.util.List;

public class Main {
    record Factura(String client, double suma, double tva) {}

    public static void main(String[] args) {
        List<Factura> facturi = List.of(new Factura("Ana", 100, 21), new Factura("Dan", 250, 52.5));

        double total = facturi.stream()
                .mapMultiToDouble((f, t) -> {
                    t.accept(f.suma());
                    t.accept(f.tva());
                })
                .sum();
        System.out.println("Total cu TVA: " + total);

        int litere = List.of("Iași", "Cluj").stream()
                .mapMultiToInt((s, t) -> t.accept(s.length()))
                .sum();
        System.out.println("Litere: " + litere);

        long kb = List.of(2L, 3L).stream()
                .mapMultiToLong((n, t) -> t.accept(n * 1024))
                .sum();
        System.out.println("Octeți: " + kb);
    }
}

Rezultat

Total cu TVA: 423.5
Litere: 8
Octeți: 5120

Exemplul 3: Doar valorile de un anumit tip

O listă cu obiecte amestecate; păstrăm doar textele, deja convertite la String.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Object> amestec = List.of("Ana", 12, "Brașov", 3.5, "Radu");
        List<String> texte = amestec.stream()
                .<String>mapMulti((o, t) -> {
                    if (o instanceof String s) {
                        t.accept(s);
                    }
                })
                .toList();
        System.out.println(texte);
    }
}

Rezultat

[Ana, Brașov, Radu]

Greșeli frecvente

  • Nu scrii tipul rezultatului (.<String>mapMulti). Compilatorul deduce Object și toList() devine List<Object>.
  • Încerci să returnezi o valoare din lambda. mapMulti nu folosește valoarea returnată; valorile se trimit doar prin accept.

Comenzi înrudite

  • Stream.flatMap: Transformă fiecare element într-un stream și lipește toate aceste stream-uri într-unul singur.
  • Stream.flatMapToInt: Ca flatMap, dar fiecare element produce un stream de numere primitive, iar rezultatul este un IntStream, LongStream sau DoubleStream.
  • Consumer: O acțiune care primește o valoare și nu returnează nimic (afișează, salvează, trimite); o rulezi cu accept.
  • Stream.filter: Păstrează în stream doar elementele care îndeplinesc o condiție.