Ответ 1
TL; DR
Да, заказ гарантирован.
Документация API Stream.collect()
Исходным местом является просмотр того, что определяет, является ли сокращение одновременным или нет. Stream.collect()
описание говорит следующее:
Если поток параллелен, а
Collector
- concurrent, и либо поток неупорядочен, либо коллекционер unordered, тогда будет выполнено параллельное сокращение (см.Collector
для получения подробной информации о параллельном сокращении.)
Первое условие выполнено: поток параллелен. Как насчет второго и третьего: является ли Collector
одновременным и неупорядоченным?
Документация API Collectors.toList()
toList()
документация гласит:
Возвращает a
Collector
, который накапливает входные элементы в новыйList
. Нет гарантий относительно типа, изменчивости, сериализуемости или безопасности потоковList
; если требуется больше контроля над возвращаемымList
, используйтеtoCollection(Supplier)
.Returns:
сборщик, который собирает все входные элементы в список, в порядке встречи
Операция, которая работает в порядке поиска, работает с элементами в их первоначальном порядке. Это отменяет параллельность.
Код реализации
Проверка реализации Collectors.java
подтверждает, что toList()
содержит не признаки CONCURRENT
или UNORDERED
.
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
// ...
static final Set<Collector.Characteristics> CH_ID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
Обратите внимание, что у коллектора есть набор признаков CH_ID
, который имеет только один признак IDENTITY_FINISH
. CONCURRENT
и UNORDERED
не существует, поэтому редукция не может быть параллельной.
Неконкурентная редукция означает, что если поток параллелен, сбор может продолжаться параллельно, но он будет разделен на несколько промежуточных результатов с ограничением потока, которые затем объединяются. Это гарантирует, что объединенный результат находится в порядке поиска.
См. также: Почему параллельный поток собирается последовательно в Java 8