0Pricing
Java Academy · Урок

Spliterator: разделение для параллельной обработки

Реализуйте собственный Spliterator, чтобы предоставить данные предметной области как источник потока, поддерживающий разделение.

«Spliterator: разделение для параллельной обработки» — бесплатный урок Java Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Что такое Spliterator

Spliterator (разделяемый итератор) — это основной механизм потоков. Он обходит элементы и может разделить себя на две части для параллельной обработки.

Основные методы Spliterator

Четыре основных метода: tryAdvance (обработка одного элемента), forEachRemaining (обработка всех оставшихся элементов), trySplit (разделение на две части), estimateSize (оценка количества элементов).

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

Характеристики Spliterator

Spliterator объявляют свои характеристики с помощью битовых флагов: 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

Как работает trySplit

trySplit() возвращает новый Spliterator, охватывающий примерно половину оставшихся элементов. Исходный охватывает другую половину. Возвращайте null, если разделение невозможно.

// ArrayList Spliterator splits efficiently at midpoint:
// [0,1,2,3,4,5] -> [0,1,2] (new) + [3,4,5] (original)

Создание пользовательского Spliterator

Реализуйте Spliterator<T>, чтобы представить пользовательскую структуру данных как источник потока. Определите 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; }
}

Создание потока из Spliterator

Используйте StreamSupport.stream(spliterator, parallel), чтобы создать поток из любого Spliterator — связующее звено между пользовательскими источниками данных и 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 для бинарного дерева

Пользовательские Spliterator обеспечивают параллельную обработку структур, не являющихся списками, например деревьев. trySplit возвращает Spliterator левого поддерева, сохраняя правое.

Эффективность параллельной обработки и качество разделения

Параллельные потоки рекурсивно разделяются, пока части не станут достаточно маленькими для одного потока. Для качественного разделения необходимо, чтобы estimateSize давал точную оценку, а части были примерно равными.

forEachRemaining для пакетной обработки

Если разделение не требуется, переопределите forEachRemaining для пакетной обработки, позволяющей избежать накладных расходов на каждый элемент при вызове tryAdvance в цикле.

@Override
public void forEachRemaining(Consumer<? super Integer> action) {
    for (int i = start; i < end; i++) action.accept(i);
    start = end; // mark as exhausted
}

Spliterator и Iterator

Iterator: только последовательный обход, без оценки размера и разделения. Spliterator: поддерживает параллельную обработку, предоставляет характеристики и оценку размера, предназначен для API потоков.

Быстрая проверка

Что возвращает trySplit(), если разделение невозможно?

Итоги

Spliterator — это механизм параллельных потоков. Реализуйте tryAdvance, trySplit, estimateSize и characteristics, чтобы предоставлять пользовательские структуры данных как потоки. Используйте StreamSupport.stream(sp, true) для перехода к параллельной обработке.

Часто задаваемые вопросы

Урок «Spliterator: разделение для параллельной обработки» бесплатный?

Да — полный текст урока «Spliterator: разделение для параллельной обработки» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Spliterator: разделение для параллельной обработки»?

Реализуйте собственный Spliterator, чтобы предоставить данные предметной области как источник потока, поддерживающий разделение. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Spliterator: разделение для параллельной обработки»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. flatMap для вложенных коллекций
  2. Параллельные потоки: производительность и подводные камни
  3. Spliterator: разделение для параллельной обработки
  4. Бесконечные потоки с iterate и generate
← Назад к Java Academy