Close Java 8 Stream

JavaJava 8Java Stream

Java Problem Overview


If we use Java 8 Stream like list.stream().filter(....).collect(..)..... When is it closed this stream?

Is it good practice that we close the stream us as the next example?

Stream<String> stream = list.stream();
String result = stream.limit(10).collect(Collectors.joining(""));
stream.close();

Java Solutions


Solution 1 - Java

It is generally not necessary to close streams at all. You only need to close streams that use IO resources.

From the Stream documentation:

> 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.)

If you need to close a stream, then best practice would be to use the try-with-resources statement:

try ( Stream<String> stream = Files.lines(path, charset) ) {
    // do something
}

Solution 2 - Java

Absolutely, by default you should close a stream.

A stream is a very generic API; the whole point is that it represents a stream of data without requiring the consumer of that data to understand where the data is coming from.

Closing a stream which does not need closing has no cost; failing to close a stream which needs closing may cause serious issues. How sure are you that the code you are writing, which currently consumes a stream of data which does not require closing, will never be repurposed to consume a different type of stream that does require closing?

I just finished refactoring a ton of code which used to use an in-memory database to use a SQL back-end instead. The code in question used streams a lot, and for good reason. Encapsulating a JDBC result set in a stream meant that I could (...I thought) achieve my goal quite easily. But... my new stream encapsulated a resource that required closing, whereas the old stream did not. Because the original developer (in this case me, I'm kicking myself) did not close the streams, much tedious debugging was required.

Solution 3 - Java

I have to add that by default streams are not closed at all!

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

// "--" is not printed at all:
list.stream().onClose(()->System.out.println("--")).forEach(x -> System.out.println(x));

System.out.println("with try(){}:");

// "--" is printed:
try (Stream<Integer> stream = list.stream() ) {
    stream.onClose(() -> System.out.println("--")).forEach(x -> System.out.println(x));
}

Solution 4 - Java

One of the streams that you need to close are the ones coming from org.hibernate.query.Query#getResultStream

You could use try-with-resources for that:

try (Stream<SomeEntity> resultStream = query.getResultStream()) {
    // process the stream
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPauView Question on Stackoverflow
Solution 1 - JavakapexView Answer on Stackoverflow
Solution 2 - JavaJonathan EssexView Answer on Stackoverflow
Solution 3 - Java18446744073709551615View Answer on Stackoverflow
Solution 4 - Javapremek.vView Answer on Stackoverflow