Как обеспечить порядок обработки в потоках java8?

Я хочу обработать списки внутри java-объекта XML. Я должен обеспечить обработку всех элементов, чтобы я их получил.

Должен ли я поэтому называть sequential на каждом stream я использую? list.stream().sequential().filter().forEach()

Или достаточно ли просто использовать поток, если я не использую parallelism? list.stream().filter().forEach()

Ответ 1

Вы задаете неправильный вопрос. Вы спрашиваете о sequential vs. parallel, тогда как вы хотите обрабатывать элементы по порядку, поэтому вам нужно спросить о заказе. Если у вас есть упорядоченный поток и выполняются операции, которые гарантируют поддержание порядка, не имеет значения, обрабатывается ли поток параллельно или последовательно; реализация будет поддерживать порядок.

Упорядоченное свойство отличается от параллельного vs последовательного. Например. если вы вызываете stream() в HashSet, поток будет неупорядоченным, а вызов stream() в List возвращает упорядоченный поток. Обратите внимание, что вы можете вызвать unordered(), чтобы освободить контракт на заказ и потенциально увеличить производительность. Как только поток не имеет порядка, нет способа восстановить заказ. (Единственный способ превратить неупорядоченный поток в упорядоченный - вызвать sorted, однако полученный результат не обязательно является первоначальным порядком).

См. также раздел "Заказ" пакета java.util.stream документация.

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

Это может быть очень тонким, например. Stream.iterate(T,UnaryOperator) создает упорядоченный поток, а Stream.generate(Supplier) создает неупорядоченный поток. Обратите внимание, что вы также сделали распространенную ошибку в своем вопросе, поскольку forEach не поддерживает порядок. Вы должны использовать forEachOrdered, если хотите обработать элементы потоков в гарантированном порядке.

Итак, если ваш List в вашем вопросе действительно является java.util.List, его метод stream() вернет упорядоченный поток, а filter не изменит порядок. Поэтому, если вы вызываете list.stream().filter() .forEachOrdered(), все элементы будут обрабатываться последовательно по порядку, тогда как для list.parallelStream().filter().forEachOrdered() элементы могут обрабатываться параллельно (например, фильтром), но действие терминала будет по-прежнему вызываться по порядку (что, очевидно, уменьшит преимущество параллельного выполнения).

Если вы, например, используете операцию типа

List<…> result=inputList.parallelStream().map(…).filter(…).collect(Collectors.toList());

вся операция может выиграть от параллельного выполнения, но полученный список всегда будет в правильном порядке, независимо от того, используете ли вы параллельный или последовательный поток.

Ответ 2

list.stream(). Последовательное(). Фильтр(). Foreach()

всегда обрабатывает список, чтобы упорядочить список.

Однако, если мы используем

list.stream(). Параллельны()

тогда порядок не гарантируется для остальных операций.