0Pricing
Java Academy · Lekcja

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 6

Wł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, SUBSIZED

Jak 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); // 500000

Spliterator 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

  1. flatMap dla zagnieżdżonych kolekcji
  2. Strumienie równoległe: wydajność i pułapki
  3. Spliterator: dzielenie na potrzeby równoległości
  4. Nieskończone strumienie za pomocą iterate i generate
← Powrót do Java Academy