Spliterator: dzielenie na potrzeby równoległości
Proszę zaimplementować własny Spliterator, aby udostępnić dane domenowe jako źródło strumienia, które można dzielić.
Spliterator: dzielenie na potrzeby równoległości to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Czym jest Spliterator?
Spliterator (iterator z możliwością podziału) to podstawowy mechanizm leżący u podstaw strumieni. Iteruje po elementach i może podzielić się na dwie części na potrzeby przetwarzania równoległego.
Najważniejsze metody Spliteratora
Cztery podstawowe metody to: tryAdvance (przetwarza jeden element), forEachRemaining (przetwarza wszystkie pozostałe elementy), trySplit (dzieli na dwie części) oraz estimateSize (szacuje liczbę elementów).
Spliterator<Integer> sp = List.of(1,2,3,4,5,6).spliterator();
Spliterator<Integer> half = sp.trySplit(); // splits off first ~half
half.forEachRemaining(System.out::println); // 1 2 3
sp.forEachRemaining(System.out::println); // 4 5 6Właściwości Spliteratora
Spliterator deklaruje swoje właściwości za pomocą flag bitowych: SIZED, ORDERED, DISTINCT, SORTED, NONNULL, IMMUTABLE, CONCURRENT, SUBSIZED.
Spliterator<String> sp = List.of("a","b","c").spliterator();
System.out.println(Integer.toBinaryString(sp.characteristics()));
// Characteristics include ORDERED, SIZED, SUBSIZEDJak działa trySplit
trySplit() zwraca nowy Spliterator obejmujący w przybliżeniu połowę pozostałych elementów. Oryginalny Spliterator obejmuje drugą połowę. Jeśli podział nie jest możliwy, należy zwrócić null.
// ArrayList Spliterator splits efficiently at midpoint:
// [0,1,2,3,4,5] -> [0,1,2] (new) + [3,4,5] (original)Tworzenie własnego Spliteratora
Należy zaimplementować Spliterator<T>, aby udostępnić własną strukturę danych jako źródło strumienia. Aby umożliwić przetwarzanie równoległe, należy zdefiniować trySplit.
public class RangeSpliterator implements Spliterator<Integer> {
private int start, end;
public RangeSpliterator(int start, int end) { this.start=start; this.end=end; }
public boolean tryAdvance(Consumer<? super Integer> action) {
if (start >= end) return false;
action.accept(start++); return true;
}
public Spliterator<Integer> trySplit() {
int mid = (start + end) / 2;
if (mid <= start) return null;
RangeSpliterator prefix = new RangeSpliterator(start, mid);
this.start = mid; return prefix;
}
public long estimateSize() { return end - start; }
public int characteristics() { return ORDERED | SIZED | SUBSIZED | IMMUTABLE; }
}Tworzenie strumienia ze Spliteratora
Należy użyć StreamSupport.stream(spliterator, parallel), aby utworzyć strumień z dowolnego spliteratora — jest to most między niestandardowymi źródłami danych a Stream API.
Spliterator<Integer> sp = new RangeSpliterator(0, 1_000_000);
Stream<Integer> stream = StreamSupport.stream(sp, true); // true = parallel
long count = stream.filter(n -> n % 2 == 0).count();
System.out.println(count); // 500000Spliterator dla drzewa binarnego
Własne Spliteratora umożliwiają przetwarzanie równoległe struktur niebędących listami, takich jak drzewa. trySplit zwraca spliterator lewego poddrzewa i zachowuje prawe poddrzewo.
Wydajność równoległa i jakość podziału
Strumienie równoległe dzielą dane rekurencyjnie, aż fragmenty będą wystarczająco małe, aby obsłużyć je w jednym wątku. Dobry podział wymaga, aby estimateSize było dokładne, a podzielone fragmenty miały zbliżony rozmiar.
forEachRemaining do przetwarzania zbiorczego
Jeśli dzielenie nie jest potrzebne, należy przesłonić forEachRemaining, aby umożliwić przetwarzanie zbiorcze, które eliminuje narzut związany z wywoływaniem tryAdvance dla każdego elementu w pętli.
@Override
public void forEachRemaining(Consumer<? super Integer> action) {
for (int i = start; i < end; i++) action.accept(i);
start = end; // mark as exhausted
}Spliterator a Iterator
Iterator: tylko sekwencyjny, bez informacji o rozmiarze i bez możliwości dzielenia. Spliterator: obsługuje przetwarzanie równoległe, udostępnia właściwości i szacowany rozmiar oraz jest przeznaczony dla Stream API.
Szybki test
Co zwraca trySplit(), gdy podział nie jest możliwy?
Powtórzenie
Spliterator jest silnikiem strumieni równoległych. Należy zaimplementować tryAdvance, trySplit, estimateSize i characteristics, aby udostępnić własne struktury danych jako strumienie. Aby uruchomić przetwarzanie równoległe, należy użyć StreamSupport.stream(sp, true).
Często zadawane pytania
Czy lekcja „Spliterator: dzielenie na potrzeby równoległości” jest bezpłatna?
Tak — pełny tekst „Spliterator: dzielenie na potrzeby równoległości” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Spliterator: dzielenie na potrzeby równoległości”?
Proszę zaimplementować własny Spliterator, aby udostępnić dane domenowe jako źródło strumienia, które można dzielić. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Spliterator: dzielenie na potrzeby równoległości”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- flatMap dla zagnieżdżonych kolekcji
- Strumienie równoległe: wydajność i pułapki
- Spliterator: dzielenie na potrzeby równoległości
- Nieskończone strumienie za pomocą iterate i generate