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.