Pull to refresh

Comments 8

Очень и очень годно.

Несмотря на то, что лямбды и библиотека операций над коллекциями — это очень большой шаг вперёд, он всё равно какой-то половинчатый. Многих идиом, совершенно естественных в аналогичных библиотеках в других языках, просто нет — чего только стоит отсутствие банального foldLeft и, например, возможности разделить поток на голову и хвост без преобразования в итератор. Несериализуемый Optional, который рекомендуется использовать только и исключительно в контексте коллекций. Много боли также от несовместимости примитивов и объектных типов. Такие библиотеки, как ваша, здорово с этим помогут :)
Шепотом: а в scala это все есть из коробки!
Да, именно поэтому я и говорю про половинчатость :) к счастью, я давно уже работаю только на скале, но за джаву у меня, можно сказать, «душа болит») Мне не очень понятно, зачем авторы Java пошли по ущербному пути, не пользуясь всеми существующими наработками. Когда я спросил на Stackoverflow, почему в библиотеке потоков нет самой обычной последовательной свёртки, мне ответили, что
the API doesn't provide this is that the designers don't want encourage people to write non-parallelizable code

что, на мой взгляд, является полным BSом.
1. Есть «почти foldLeft» — reduce.
2. Стримы в скале и джаве — это разные вещи. И если в первой это совершенно конкретная структура данных вида (head, => tail), то во второй это обобщенная (unordered/unsorted/undistinct/etc) штука с параллельной обработкой. И вся половинчатость как раз следствие этого. В частности, невозможность честного foldLeft, т.к. при параллельной обработке понятия left вообще не существует. И невозможность «разделить поток на голову и хвост», т.к. у неупорядоченного стрима нет головы (грубо говоря, если бы этот метод был, он имел бы полное право вернуть разные значения для двух последовательных вызовов).

Stream API решает меньше задач, чем мог бы. Но делает это качественно. Имхо, это лучше альтернативы — делать массу всего, но «тут не всегда, здесь никогда, а вот там можно, но надо не забыть свериться с джавадоком».

А вот если очень хочется иметь небезопасные (в общем случае) операции, то всегда можно написать библиотеку, что и сделал Автор.
reduce это ни разу ни foldLeft, о чём я как раз и пишу. Однородная свёртка удобна далеко не всегда.

Стримы в Java могут быть последовательными — у них есть соответствующая характеристика.

грубо говоря, если бы этот метод был, он имел бы полное право вернуть разные значения для двух последовательных вызовов

Этот метод мог бы иметь возвращаемое значение типа (T, Stream<T>) (с поправкой на то, что в джаве нету кортежей) и поглощать исходный поток — как, в общем-то, сейчас все операции над стримами и работают.

Я вполне в курсе, почему API выглядит именно так. Про проблемы стримового API уже много писали. В частности, эта широко рекламируемая параллелизация одной строкой кода в 95% случаев не нужна, а там, где нужна, как правило гораздо лучше воспользоваться специализированным под конкретную задачу решением. Разработчикам Java нужно было бы исходить из практичности, а не из весьма сомнительных идеалов.
Библиотека хорошая, спасибо за труд!

хочется вместо терминального forEach воспользоваться обычным циклом for

Это специально — т.к. поток может быть параллельным.
Если нужен итератор, лучше в конце сделать toList() и делать for уже на нем.
Пожалуйста!

Да, я хотел дописать, что на параллельном потоке итератор лучше не использовать, но потом решил, что это очевидно :-)
Это не всегда очевидно, особенно если вы не создаете поток сами, а обрабатываете уже созданный кем-то поток. Конечно, в своих личных проектах такое маловероятно, но в проектах, где работает несколько человек, допустить это легче легкого :)
Sign up to leave a comment.

Articles