Gernot Neppert mcnepp02 at
Tue Jun 25 05:35:13 PDT 2013

The canical example that is being used to demonstrate potential problems
with "CloseableStreams" seems to be

try(Stream<String> s = Files.lines(path).filter(getPredicate())) {
   ... // do something with s

Here, a resource leak occurs if chained method after Files.lines throws.

Maybe this simply shows that mixing Stream creation and Resource allocation
is not such a good idea in the first place.
If we go one step back and separate Resource allocation and Stream
processing, the problems go away:

try(BufferedReader reader = Files.newBufferedReader(path)) {
    Stream<String> s = reader.lines()..filter(getPredicate());
    ... // do something with s.

So, maybe we can get the best of both worlds?
Here's a proposal:

interface ResourceStream<T> extends Stream<T> {
       Opens the Resource associated with this CloseableStream.
       @return a Stream that needs to be closed after use.
   CloseableStream<T> open();

// Co-variant overrides of all the Stream-processing functions, such as:
   ResourceStream<T> filter(Predicate<? super T> filter);

Make java.nio.file.Files.lines(Path) return a ResourceStream<String>, so
the example becomes:

try(CloseableStream<String> s =
Files.lines(path).filter(getPredicate()).open()) {
    ... // do something with s.

2013/6/25 Paul Sandoz <paul.sandoz at>

> What about the following:
>   Stream s = Files.lines(path));
>   s = s.filter(goGetMeAPredicate()); // Exception thrown
>   return s.collect(toList());
>   ...
>   Predicate goGetMeAPredicate() {
>     throw new RuntimeException();
>   }
> There may be other stuff being performed in conjunction with the stream
> holding a GCR stuff.
> Are you proposing that GCR state should be lazily initialized when the
> terminal operation commences with appropriate management of that state in
> the AutoCloseable? That would also result in errors at a distance.
> Paul.
> On Jun 25, 2013, at 9:30 AM, Remi Forax <forax at> wrote:
> > As someone said one the lambda-dev mailing list, there is no TWR in C#
> because close is called at the end of the for-each instruction.
> > Why do you want user to care about releasing resources manually if this
> can be done automatically ?
> >
> > A Stream is an abstraction over a loopy thing, so like in C#, the Stream
> should call close at the end if the source is an AutoCloseable.
> > Thus either the Spliterator takes care of the resource, but conceptually
> a Spliterator is more an abstraction over a traversal algorithm
> > or the Stream takes care of the resource.
> > Thus the solution is easy, instead of constructing a Stream with 2
> parameters, the supplier of spliterator and the characteristics,
> > we need a third parameter, an AutoCloseable that may be null and in the
> implementation of all terminal methods of Stream,
> > we have to enclose the 'loop' over the spliterator inside a TWR.
> >
> > Sometimes the simple solution is the best one.
> > Rémi
> >
> >
> >
> >
> >

More information about the lambda-libs-spec-observers mailing list