Javadoc для Stream.forEach
говорит (акцент мой):
Поведение этой операции явно недетерминировано. Для параллельных поточных конвейеров эта операция не гарантирует уважения порядка встречи потока, так как это принесет жертву преимущества параллелизма. Для любого данного элемента действие может выполняться в любое время и в любом потоке, который выбирает библиотека. Если действие обращается к общему состоянию, оно отвечает за предоставление необходимой синхронизации.
Тот же текст присутствует в Java 9 Early Access Javadoc.
Первое предложение ("явно недетерминированное") предлагает (но явно не говорит), что этот порядок не сохраняется. Но следующее предложение, которое явно говорит, что порядок не сохраняется, обусловлен "для параллельных потоковых конвейеров", и это условие было бы лишним, если бы предложение применялось независимо от параллелизма. Это оставляет мне неуверенность в том, что forEach сохраняет порядок поиска для последовательных потоков.
В этом ответе указывается место, где реализация библиотеки потоков вызывает .sequential().forEach(downstream)
. Это предполагает, что forEach предназначен для сохранения порядка последовательных потоков, но также может быть просто ошибкой в библиотеке.
Я обошел эту двусмысленность в своем собственном коде, используя forEachOrdered
чтобы быть в безопасности, но сегодня я обнаружил, что в среде IDE NetBeans "использовать функциональные операции" hint будет конвертировать
for (Foo foo : collection)
foo.bar();
в
collection.stream().forEach((foo) -> {
foo.bar();
});
который вводит ошибку, если forEach не сохраняет порядок встреч. Прежде чем сообщать об ошибке с NetBeans, я хочу знать, что на самом деле гарантирует библиотека, подкрепленная источником.
Я ищу ответ из авторитетных источников. Это может быть явный комментарий в реализации библиотеки, обсуждение списков рассылки разработки Java (Google ничего не нашел для меня, но, может быть, я не знаю волшебных слов), или выражение разработчиков библиотеки (из которых я знаю два, Брайан Гетц и Стюарт Маркс, активны в переполнении стека). (Пожалуйста, не отвечайте "просто используйте forEachOrdered вместо" - я уже это делаю, но я хочу знать, не ошибается ли код).