List.spliterator în Java

Returnează un Spliterator: un iterator care se poate împărți în bucăți, folosit de stream-uri pentru prelucrare în paralel.

Sintaxă
default Spliterator<E> spliterator()

// metode din Spliterator
boolean tryAdvance(Consumer<? super T> action)
void forEachRemaining(Consumer<? super T> action)
Spliterator<T> trySplit()
long estimateSize()

Ce face List.spliterator

Un Spliterator („split” + „iterator”) parcurge elementele ca un iterator, dar poate și să se împartă: trySplit() desprinde o parte din elemente într-un spliterator nou, ca două fire de execuție să lucreze fiecare pe bucata lui. Stream-urile (stream(), parallelStream()) folosesc spliteratorul în spate.

Metodele de bază: tryAdvance(f) prelucrează un singur element și returnează false când nu mai sunt; forEachRemaining(f) le prelucrează pe toate cele rămase; estimateSize() spune câte elemente au mai rămas. Atât List, cât și Set (și orice Collection) au metoda spliterator().

În programele obișnuite rareori ai nevoie direct de spliterator: un for-each sau un stream sunt mai simple. Este util când scrii propriile surse de date pentru stream-uri.

Ce returnează

Un Spliterator peste elementele colecției.

Exemple

Exemplul 1: tryAdvance și forEachRemaining

import java.util.List;
import java.util.Spliterator;

public class Main {
    public static void main(String[] args) {
        List<String> orase = List.of("Iași", "Cluj", "Brașov", "Constanța");
        Spliterator<String> sp = orase.spliterator();
        System.out.println("Rămase: " + sp.estimateSize());

        sp.tryAdvance(o -> System.out.println("Primul: " + o));
        System.out.println("Rămase: " + sp.estimateSize());
        sp.forEachRemaining(o -> System.out.println("Apoi: " + o));
        System.out.println("Mai este ceva? " + sp.tryAdvance(o -> {}));
    }
}

Rezultat

Rămase: 4
Primul: Iași
Rămase: 3
Apoi: Cluj
Apoi: Brașov
Apoi: Constanța
Mai este ceva? false

Exemplul 2: Împărțirea în două bucăți cu trySplit

Pentru un ArrayList, trySplit desprinde prima jumătate a elementelor; spliteratorul original rămâne cu a doua jumătate.

import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;

public class Main {
    public static void main(String[] args) {
        List<Integer> numere = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8));
        Spliterator<Integer> a = numere.spliterator();
        Spliterator<Integer> b = a.trySplit();

        System.out.print("Bucata desprinsă: ");
        b.forEachRemaining(n -> System.out.print(n + " "));
        System.out.print("\nBucata rămasă:    ");
        a.forEachRemaining(n -> System.out.print(n + " "));
        System.out.println();
    }
}

Rezultat

Bucata desprinsă: 1 2 3 4 
Bucata rămasă:    5 6 7 8

Exemplul 3: Spliterator pe un Set sortat

Spliteratorul are „caracteristici”: pentru un TreeSet, de exemplu, știe că elementele sunt sortate și distincte.

import java.util.Set;
import java.util.Spliterator;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        Set<String> culori = new TreeSet<>(Set.of("roșu", "galben", "albastru"));
        Spliterator<String> sp = culori.spliterator();
        System.out.println("SORTED: " + sp.hasCharacteristics(Spliterator.SORTED));
        System.out.println("DISTINCT: " + sp.hasCharacteristics(Spliterator.DISTINCT));
        sp.forEachRemaining(System.out::println);
    }
}

Rezultat

SORTED: true
DISTINCT: true
albastru
galben
roșu

Greșeli frecvente

  • Folosești același spliterator de două ori: după ce a parcurs elementele, nu mai returnează nimic. Cere unul nou cu spliterator().
  • Modifici colecția în timp ce o parcurgi cu spliteratorul: comportamentul este același ca la iterator (ConcurrentModificationException).

Comenzi înrudite

  • List.iterator: iterator parcurge lista înainte; listIterator poate merge și înapoi, poate înlocui și insera elemente.
  • Collection.stream: Creează un Stream peste elementele colecției, ca să le filtrezi, transformi, sortezi sau aduni într-un rezultat.
  • Iterator: Obiectul care parcurge o colecție element cu element: hasNext() întreabă dacă mai urmează ceva, next() îl dă pe următorul.
  • Iterable: Interfața care permite bucla for-each: orice obiect Iterable poate fi parcurs cu for (T x : obiect) și cu forEach.