RFR: 8274412: Add a method to Stream API to consume and close the stream without using try-with-resources
Remi Forax
forax at univ-mlv.fr
Sat Oct 9 10:29:34 UTC 2021
----- Original Message -----
> From: "Tagir F.Valeev" <tvaleev at openjdk.java.net>
> To: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Sent: Lundi 4 Octobre 2021 08:51:55
> Subject: RFR: 8274412: Add a method to Stream API to consume and close the stream without using try-with-resources
> 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")).applyAndClose(Stream::toList);
I would prefer the method to be called applyAndClose() because it is what the method does, it applies the function and closes the stream.
There are two missing information in the javadoc
- the function taken as parameter should not return a stream, because the stream will be closed
This is not okay
List<Path> list = Files.list(Path.of("/etc")).applyAndClose(s -> s).toList();
- if there are intermediary operations, they have to be done in the function taken as parameter and not before calling applyAndClose()
This is okay
List<Integer> list = Files.list(Path.of("/etc")).applyAndClose(s -> s.map(path -> Integer.parseInt(path.toString())).toList());
This is not okay
List<Integer> list = Files.list(Path.of("/etc")).map(path -> Integer.parseInt(path.toString())).applyAndClose(Stream::toList);
In both case, IDEs can help, but i think it should be written explicitly in the javadoc.
>
> -------------
>
> 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