Spliterator против Stream.Builder

Я прочитал несколько вопросов, как создать конечный Stream ( Конечный сгенерированный поток в Java - как его создать?, Как останавливаются потоки?).

В ответах предлагалось реализовать Spliterator. Spliterator будет реализовывать логику, как и какой элемент предоставить следующим (tryAdvance). Но есть два других нестандартных метода trySplit и estimateSize(), которые мне придется реализовать.

В JavaDoc Spliterator говорится:

An object for traversing and partitioning elements of a source. The source of elements covered by a Spliterator could be, for example, an array, a Collection, an IO channel, or a generator function. ... The Spliterator API was designed to support efficient parallel traversal in addition to sequential traversal, by supporting decomposition as well as single-element iteration. ...

С другой стороны, я мог бы реализовать логику перехода к следующему элементу вокруг Stream.Builder и обхода Spliterator. При каждом продвижении я звонил accept или add и в конце build. Так что это выглядит довольно просто.

Что говорит JavaDoc?

A mutable builder for a Stream. This allows the creation of a Stream by generating elements individually and adding them to the Builder (without the copying overhead that comes from using an ArrayList as a temporary buffer.)

Используя StreamSupport.stream, я могу использовать Spliterator для получения Stream. А также Builder предоставит Stream.

Когда следует / можно использовать Stream.Builder?
Только если Spliterator не будет более эффективным (например, из-за того, что источник не может быть разбит на разделы и его размер не может быть оценен)?

Все сводится к тому, чтобы толкать или тянуть.

Johannes Kuhn 14.09.2018 18:50

Я просто хочу добавить, что, хотя я написал несколько сплитераторов самостоятельно, это никогда не было забавной историей, возможно, для Хольгера это козырёк; но если вам действительно нужны дополнительные функции, Spliterator - это то, что вам нужно.

Eugene 14.09.2018 20:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
2
764
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

On the other hand I could implement the logic how to advance to the next element around a Stream.Builder and bypass a Spliterator. On every advance I would call accept or add and at the end build. So it looks quite simple.

Да и нет. Это просто является, но я не думаю, что вы понимаете модель использования:

A stream builder has a lifecycle, which starts in a building phase, during which elements can be added, and then transitions to a built phase, after which elements may not be added. The built phase begins when the build() method is called, which creates an ordered Stream whose elements are the elements that were added to the stream builder, in the order they were added.

(Javadocs)

В частности, нет, вы не должны вызывать метод Stream.Builder или acceptadd при любом продвижении потока. Вам необходимо заранее предоставить все объекты для потока в. Затем вы build(), чтобы получить поток, который предоставит все объекты, которые вы добавили ранее. Это аналогично добавлению всех объектов в List и последующему вызову метода List этого stream().

Если это служит вашим целям и вы действительно можете делать это эффективно, тогда отлично! Но если вам нужно генерировать элементы по мере необходимости, с лимитом или без него, Stream.Builder вам не поможет. Spliterator может.

вы не будете вызывать метод accept или add Stream.Builder при продвижении потока - Думаю, вы меня неправильно поняли. Я сказал, что могу построить логику вокруг Stream.Builder.accept, а не на Stream. Я имел в виду, что таким образом я могу добавить каждый элемент в Stream.Builder, аналогично тому, как Spliterator.tryAdvance предоставляет каждый элемент.
LuCio 14.09.2018 19:23

@LuCio tryAdvanceпотенциально предоставляет каждый элемент, но может не вызываться для каждого элемента, поскольку потоку они могут не понадобиться. Но вы должны вызвать Stream.Builder.accept или add для каждого элемента, прежде чем вы сможете создать поток, не зная, все ли они нужны. Вызов метода для каждого элемента или реализация метода, потенциально обеспечивающего каждый элемент, представляют собой принципиально разные структуры кода. Обычно это естественный выбор.

Holger 14.09.2018 19:27

@Holger Да. Это важное различие, которое я только что прочитал из вашего ответа.

LuCio 14.09.2018 19:41

@LuCio, вы написали: «Каждый раз я называл accept или add, а в конце - build». И да, конечно, вы можете создать поток, используя Stream.Builder.advance и, в конечном итоге, Stream.Builder.build. Вопрос в сроках. Как я уже сказал, если вы можете передать все элементы в Stream.Builder заранее, до того, как начнете обрабатывать поток, то это нормально. Но вы не можете вызывать accept или add одновременно с продвижением по потоку. В любом случае, если вы хотели сказать не это, тогда хорошо.

John Bollinger 14.09.2018 20:53

@JohnBollinger Thx за разъяснения.

LuCio 15.09.2018 00:09
Ответ принят как подходящий

Обратите внимание, что вы можете расширить Spliterators.AbstractSpliterator. Затем остается реализовать только tryAdvance.

Так что сложность реализации Spliterator не выше.

Принципиальное отличие состоит в том, что метод SpliteratortryAdvance вызывается только тогда, когда требуется новый элемент. Напротив, Stream.Builder имеет место хранения, который будет заполнен всеми элементами потока, прежде чем вы сможете получить поток.

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

Конструктор - это лучший выбор, когда создание элементов неоднородно, поэтому вы не можете выразить создание элемента по запросу. Подумайте о ситуациях, когда в противном случае вы бы использовали Stream.of(…), но он оказывается негибким.

Например. у вас есть Stream.of(a, b, c, d, e), но теперь оказывается, что c и d необязательны. Итак, решение

Stream.Builder<MyType> builder = Stream.builder();
builder.add(a).add(b);
if (someCondition) builder.add(c).add(d);
builder.add(e).build()
   /* stream operations */

Другими вариантами использования являются этот ответ, где Consumer был необходим для запроса существующего сплитератора и последующей передачи значения обратно в Stream, или этот ответ, где структура без произвольного доступа (иерархия классов) должна передаваться в обратном порядке.

Я думаю, что ленивое оценивание - это очень важный и отличительный момент. Пример для Stream.Builder, где c и d являются необязательными, (если я вас правильно понял) похож на этот вопрос. Я собирался использовать Stream.Builder в качестве решения, но не был уверен, подходит ли оно.

LuCio 14.09.2018 19:37

Я тупой, я новичок в java, и я вижу функции Stream.builder () и build (), пожалуйста, помогите мне понять !!!

nitinsridar 01.09.2019 18:14

@nitinsridar, в чем именно заключается ваш вопрос?

Holger 02.09.2019 09:43

Что такое буйдер? Я вижу в elasticsearch, apache kafka, но я не понимаю, что на самом деле делает строитель? @Holger

nitinsridar 02.09.2019 10:32

@nitinsridar метод Stream.builder(), который возвращает экземпляр класс Stream.Builder.

Holger 02.09.2019 10:35

Другие вопросы по теме