6

When collecting a java.util.stream.Stream, why is not its method void close() called ?

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
Blackrush
  • 117
  • 9
  • Just a guess, but maybe it's so that there are no "it's automatic _except for_" cases. For instance, what if you construct a `Stream` but then don't actually use it (for whatever reason)? It's simpler to just say that if you need a stream closed, you have to control its lifecycle yourself using try-with-resources. – yshavit Aug 06 '14 at 19:59

2 Answers2

4

Per the Stream javadoc,

Streams have a BaseStream.close() method and implement AutoCloseable, but nearly all stream instances do not actually need to be closed after use. Generally, only streams whose source is an IO channel (such as those returned by Files.lines(Path, Charset)) will require closing. Most streams are backed by collections, arrays, or generating functions, which require no special resource management. (If a stream does require closing, it can be declared as a resource in a try-with-resources statement.)

So, it sounds like you need to use a try-with-resources Statement.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 3
    Is there any reason, close is not called by terminal operations automatically? They cannot be reused afterwards, so there is no need to keep them open. – isnot2bad Aug 06 '14 at 19:43
  • I could see a use case for it, if the underlying stream is still usable. For instance, maybe you have a file with a bunch of `Foo`s followed by a bunch of `Bar`s. You create a `Stream` for the first part of the file, and then (reusing the same `InputStream`) a `Foo` for the rest of the file. The counter-argument to that is that this is probably an unusual case, and maybe the thing to do there would be to not use the `Stream` interface at all (but rather manually do whatever you need to do). – yshavit Aug 06 '14 at 19:47
  • That's exactly what I'm doing right now but since a Stream is used only once, I thought `void close()` was invoking on a terminal operation. It would have been really neat actually ! Wrapping the stream with a try-with-resource adds very much code noise. – Blackrush Aug 06 '14 at 21:14
0

Do you mean garbage collecting?

This would imply that the garbage collector would have to know a lot about the objects it's cleaning up. I don't think that's a good idea for a GC implementation to worry about.

Cleaning up after scarce resources is your responsibility as a developer. This is what try/finally was born for.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 2
    I totally agree with you. The thing is a stream may consume cleanable resources which is why it implements `Closeable`, and `S onClose(Runnable)`, for composability purposes. Yet, since a Stream is used only once, a terminal operation could have auto-cleaned up things, thus save much boilerplate by adding a try-with-resource statement. – Blackrush Aug 06 '14 at 21:20
  • It is the developer's responsibility to "clean up after scarce resources" by implementing close(). It should be the stream consumer's responsibility to call close(), i.e., the implementation of java.util.stream.Consumer. IMHO, terrible decision to force the developer to call it manually. – Rich MacDonald Dec 04 '18 at 14:15
  • This is changed with JDK 8 and try/with. This question and answer are 4.5 years old. – duffymo Dec 04 '18 at 14:30
  • This IS JDK 8 and any developer (like myself) who overlooks that last sentence inside the parentheses of the streams javadoc and assumes that stream collectors will automatically call close() is in for an unpleasant surprise. Also, there is a more complete discussion of the concern at https://stackoverflow.com/questions/28813637/why-doesnt-java-close-stream-after-a-terminal-operation-is-issued where Brian Goetz himself provides his views. – Rich MacDonald Dec 04 '18 at 15:15
  • No one who’s been writing Java should be surprised. Closing scarce resources has been a fact of life since 1995. – duffymo Dec 04 '18 at 15:17