In pre-Java 8 lambda-heavy libraries like Guava, the outputs use common Java Collection Framework interfaces so is easy to pass them around to external/internal APIs and still harness some lazy computation if the library method does it (e.g. lazy filter() and transform()).

However, in Java 8 Streams, the call to get a Collection/Map is terminal (i.e. eager) and it will also allocate new data structures to hold the results.

For complicated computations with multiple stages and strategy pattern in the middle, this causes a lot of unnecessary allocations due to the intermediate results.

So, do people think it is a good practice for internal APIs (i.e. strategy pattern strategies) to take and return Streams or should I just fallback to the lazy but not streamlined (pun intended I guess) Guava APIs?


My main concern with Stream is that it can only be consumed once and passing something like a Supplier<Stream<X>> looks extremely cumbersome. It almost pushes you just to pass a Collection and then re-stream() it (and paying the cost of eager evaluation at that point).

  • What, Guava & friends aren't being updated to take advantage of native streams? Commented Jul 13, 2015 at 10:32
  • 1
    Having interfaces which take and return streams really improves interoperability with the standard stream functionalities. It allows you to integrate calls to your interface into a stream pipeline.
    – Philipp
    Commented Jul 13, 2015 at 10:56
  • @KilianFoth There hasn't been any Guava release for almost a year and there are many popular articles about replacing Guava's lambda stuff with Stream; however none of them address the fact that Guava collection operations can be eager or lazy.
    – billc.cn
    Commented Jul 13, 2015 at 16:00

1 Answer 1


Laziness in Java 8 Streams works the same as it used to for Iterables in Guava: you have to pass on the Iterable to stay lazy and evaluation happens, once you build a Collection from the Iterator. Both Streams and Iterators can only be consumed once.

So for your method interfaces, the more general way (permitting laziness) is to use the Stream interface (whenever you would have used Iterable before). As @Philipp says, this allows them to be used in Stream pipelines.

Hopefully, since Stream now is an official Java standard interface, there will be more and more other libraries and functions which can efficiently work on Streams directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.