Reputation: 3070
When we concatenate streams using Stream.concat
is it possible to run a function whenever a stream gets over?
e.g.
I'm creating streams out of multiple files using Files.lines
. Now whenever a file is read completely, I need to delete it.
Upvotes: 0
Views: 528
Reputation: 298143
The close handlers of a stream composed via Stream.concat
are executed when the resulting stream is closed. Note that close handlers in general require that the code using the stream closes the stream, e.g.
try(Stream<String> s=Stream.concat(Files.lines(path1), Files.lines(path2))) {
s.forEach(System.out::println);
}
for proper closing and
try(Stream<String> s=Stream.concat(
Files.lines(path1).onClose(()->{
try { Files.delete(path1); }
catch (IOException ex) { throw new UncheckedIOException(ex); }
}),
Files.lines(path2).onClose(()->{
try { Files.delete(path2); }
catch (IOException ex) { throw new UncheckedIOException(ex); }
}))
) {
s.forEach(System.out::println);
}
for deleting the files afterwards. But in this case, the resulting stream’s close handler will invoke the source stream’s close handlers, so this doesn’t delete the files immediately after use, but after the entire operation, so it’s not much different to
try(Closeable c1=() -> Files.deleteIfExists(path1);
Closeable c2=() -> Files.deleteIfExists(path2);
Stream<String> s=Stream.concat(Files.lines(path1), Files.lines(path2)); ) {
s.forEach(System.out::println);
}
If you want a timely deletion of the files, you have to use flatMap
. The sub-streams will be closed immediately after use, regardless of whether the “outer” stream will be closed:
Stream.of(path1, path2)
.flatMap(path -> {
try { return Files.lines(path).onClose(()->{
try { Files.delete(path); }
catch (IOException ex) { throw new UncheckedIOException(ex); }
}); }
catch (IOException ex) { throw new UncheckedIOException(ex); }
})
.forEach(System.out::println);
To demonstrate the difference,
try(Stream<String> s=Stream.concat(
Stream.of("foo").onClose(()->System.out.println("foo closed")),
Stream.of("bar").onClose(()->System.out.println("bar closed")) )) {
s.forEach(System.out::println);
}
will print
foo
bar
foo closed
bar closed
whereas
Stream.of("foo", "bar")
.flatMap(x -> Stream.of(x).onClose(()->System.out.println(x+" closed")) )
.forEach(System.out::println);
will print
foo
foo closed
bar
bar closed
Upvotes: 4
Reputation: 1812
Did you tried using Stream.onClose(). Like Stream.concat().onClose()
Upvotes: 0