RFR: 8274412: Add a method to Stream API to consume and close the stream without using try-with-resources

Paul Sandoz paul.sandoz at oracle.com
Mon Oct 11 16:20:55 UTC 2021


Hi Tagir,

Do you mind if we slow down on this and let the idea bake somewhat, captured in this thread/issue/PR(draft).

I am always a little wary of compact-only or fluent-only methods, as I find them harder to justify. In this case I think there might be something more with regards to a pattern/idiom, and making it easier to not forgot to close. But, I am not sure we are there yet.

- we have had this “transform” idiom floating around for a while which is like your consumeAndClose, but without the try block.
  https://bugs.openjdk.java.net/browse/JDK-8140283
  And such a method was added to String.
There are likely other places where we could consider adding this idiom.

- I think we should explore adding the method you propose on AutoCloseable, that likely has more leverage, but we would need to do some careful analysis of code to ensure the risk to incompatibly is low.

The idioms “transform” and “transformAndClose” are I think related [*]. If we can nail down these I would feel much better about committing to them as methods on various classes.

Paul.

[*] If we ever get the notion of Haskell-like type classes in the platform I wonder if those would provide the hook, we could add later, that I am looking for so that we can corral these idioms.


> On Oct 3, 2021, at 11:51 PM, Tagir F.Valeev <tvaleev at openjdk.java.net> wrote:
> 
> Currently, when the stream holds a resource, it's necessary to wrap it with try-with-resources. This undermines the compact and fluent style of stream API calls. For example, if we want to get the `List` of files inside the directory and timely close the underlying filehandle, we should use something like this:
> 
> 
> List<Path> paths;
> try (Stream<Path> stream = Files.list(Path.of("/etc"))) {
>    paths = stream.toList();
> }
> // use paths
> 
> 
> I suggest to add a new default method to Stream interface named `consumeAndClose`, which allows performing terminal stream operation and closing the stream at the same time. It may look like this:
> 
> 
>    default <R> R consumeAndClose(Function<? super Stream<T>, ? extends R> function) {
>        Objects.requireNonNull(function);
>        try(this) {
>            return function.apply(this);
>        }
>    }
> 
> 
> Now, it will be possible to get the list of the files in the fluent manner:
> 
> 
> List<Path> list = Files.list(Path.of("/etc")).consumeAndClose(Stream::toList);
> 
> -------------
> 
> Commit messages:
> - Fix tests
> - 8274412: Add a method to Stream API to consume and close the stream without using try-with-resources
> 
> Changes: https://git.openjdk.java.net/jdk/pull/5796/files
> Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=5796&range=00
>  Issue: https://bugs.openjdk.java.net/browse/JDK-8274412
>  Stats: 140 lines in 5 files changed: 135 ins; 0 del; 5 mod
>  Patch: https://git.openjdk.java.net/jdk/pull/5796.diff
>  Fetch: git fetch https://git.openjdk.java.net/jdk pull/5796/head:pull/5796
> 
> PR: https://git.openjdk.java.net/jdk/pull/5796



More information about the core-libs-dev mailing list