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 16 07:32:24 UTC 2021
----- Original Message -----
> From: "Glavo" <zjx001202 at gmail.com>
> To: "Tagir F.Valeev" <tvaleev at openjdk.java.net>
> Cc: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Sent: Samedi 16 Octobre 2021 06:25:40
> Subject: Re: RFR: 8274412: Add a method to Stream API to consume and close the stream without using try-with-resources
> I don't think it is a perfect solution to combine the close operation
> with the terminator operation, because there are similar issues
> in the intermediate operation.
>
> Consider this use case (for example only):
>
> try (var stream = Files.list(path)
> .flatMap(dir -> {
> try {
> return Files.list(dir);
> } catch (IOException e) {
> return Stream.empty();
> }
> })) {
> // ...
> }
>
> It looks closed, but it doesn't. Closing the Stream generated by flatMap
> will not close all member Stream.
The stream is closed, from the javadoc
"Each mapped stream is closed after its contents have been placed into this stream."
> Further consideration is needed to
> deal with the problem of closing the Stream. Perhaps it is a withCleaner
> method that registers the Stream with the cleaner, or other solutions.
>
>
regards,
Rémi
>
>
> Tagir F.Valeev <tvaleev at openjdk.java.net> 于2021年10月4日周一 下午2:52写道:
>
>> 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