Java 8: Хорошая практика для передачи потоков в API для ленивых операций?

12

В лямбда-тяжелых библиотеках до Java 8, таких как Guava, в выходных данных используются общие интерфейсы Java Collection Framework, поэтому их легко передавать во внешние / внутренние API-интерфейсы и при этом использовать некоторые ленивые вычисления, если это делает метод библиотеки (например, lazy filter()and transform()).

Тем не менее, в Java 8 Streams, вызов для получения Collection/ Mapявляется терминалом (т.е. нетерпеливым), и он также выделит новые структуры данных для хранения результатов.

Для сложных вычислений с несколькими этапами и схемой стратегии в середине это вызывает много ненужных распределений из-за промежуточных результатов.

Итак, думают ли люди, что для внутренних API (т.е. стратегий шаблонов стратегий) Streamрекомендуется брать и возвращать s, или я должен просто вернуться к ленивым, но не оптимизированным (каламбур, я думаю, что) API-интерфейсам Guava?

Редактировать:

Моя главная проблема Streamзаключается в том, что его можно употреблять только один раз, а передача чего-то вроде этого Supplier<Stream<X>>выглядит чрезвычайно громоздкой. Это почти подталкивает вас к тому, чтобы просто пройти, Collectionа затем повторить stream()(и оплатить стоимость тщательной оценки в этот момент).

billc.cn
источник
Что, Guava и друзья не обновляются, чтобы воспользоваться преимуществами родных потоков?
Килиан Фот
1
Наличие интерфейсов, которые принимают и возвращают потоки, действительно улучшает совместимость со стандартными функциями потоков. Это позволяет вам интегрировать вызовы вашего интерфейса в потоковый конвейер.
Филипп
@KilianFoth На протяжении почти года не было ни одного выпуска Guava, и есть много популярных статей о замене лямбда-материала Guava на Stream; однако ни один из них не учитывает тот факт, что операции по сбору гуавы могут быть нетерпеливыми или ленивыми.
billc.cn

Ответы:

3

Ленивость в Java 8 Streams работает так же, как и для Iterables в Guava: вы должны передать Iterable, чтобы остаться ленивым, и оценка произойдет, как только вы создадите коллекцию из Iterator. Оба потока и итераторы могут быть использованы только один раз.

Поэтому для интерфейсов вашего метода более общий способ (разрешающий лень) состоит в том, чтобы использовать интерфейс Stream (всякий раз, когда вы раньше использовали Iterable). Как говорит @Philipp, это позволяет использовать их в конвейерах Stream.

Надеемся, что теперь Stream является официальным стандартным интерфейсом Java, и будет появляться все больше других библиотек и функций, которые могут эффективно работать непосредственно с Streams.

Роберт Джек Уилл
источник