Question: When I execute this code which opens a lot of files during a stream pipeline: 

```java
public static void main(String[] args) throws IOException {
    Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
            100, (path, attr) -> path.toString().endsWith(".html"))
        .map(file -> runtimizeException(() -> Files.lines(file, StandardCharsets.ISO_8859_1)))
        .map(Stream::count)
        .forEachOrdered(System.out::println);
}

```

I get an exception:

```java
java.nio.file.FileSystemException: /long/file/name: Too many open files

```

The problem is that `Stream.count` does not close the stream when it is done traversing it. But I don't see why it shouldn't, given that it is a terminal operation. The same holds for other terminal operations such as `reduce` and `forEach`. `flatMap` on the other hand closes the streams it consists of.

The documentation tells me to use a try-with-resouces-statement to close streams if necessary. In my case I could replace the `count` line with something like this:

```java
.map(s -> { long c = s.count(); s.close(); return c; } )

```

But that is noisy and ugly and could be a real inconvenience in some cases with big, complex pipelines.

So my questions are the following:

1. Why were the streams not designed so that terminal operations close the streams they are working on? That would make them work better with IO streams.
2. What is the best solution for closing IO streams in pipelines?

---

`runtimizeException` is a method that wraps checked exception in `RuntimeException`s.

Answer: 
It is possible to create a utility method that reliably closes streams in the middle of a pipeline.

This makes sure that each resource is closed with a try-with-resource-statement but avoids the need for a custom utility method, and is much less verbose than writing the try-statement directly in the lambda. 

With this method the pipeline from the question looks like this:

```
Files.find(Paths.get("Java_8_API_docs/docs/api"), 100,
        (path, attr) -> path.toString().endsWith(".html"))
    .map(file -> applyAndClose(
        () -> Files.lines(file, StandardCharsets.ISO_8859_1),
        Stream::count))
    .forEachOrdered(System.out::println);

```

The implementation looks like this:

```
/**
 * Applies a function to a resource and closes it afterwards.
 * @param sup Supplier of the resource that should be closed
 * @param op operation that should be performed on the resource before it is closed
 * @return The result of calling op.apply on the resource 
 */
private static <A extends AutoCloseable, B> B applyAndClose(Callable<A> sup, Function<A, B> op) {
    try (A res = sup.call()) {
        return op.apply(res);
    } catch (RuntimeException exc) {
        throw exc;
    } catch (Exception exc) {
        throw new RuntimeException("Wrapped in applyAndClose", exc);
    }
}

```

(Since resources that need to be closed often also throw exceptions when they are allocated non-runtime exceptions are wrapped in runtime exceptions, avoiding the need for a separate method that does that.)
The *close* of the interface *AutoCloseable* should only be called once. See the documentation of [AutoCloseable](http://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html) for more information.

If *final* operations would close the stream automatically, *close* might be invoked twice. Take a look at the following example:

```
try (Stream<String> lines = Files.lines(path)) {
    lines.count();
}

```

As it is defined right now, the *close* method on *lines* will be invoked exactly once. Regardless whether the *final* operation completes normally, or the operation is aborted with in *IOException*. If the stream would instead be closed implicitly in the *final* operation, the *close* method would be called once, if an *IOException* occurs, and *twice* if the operation completes successfully.