ffff
ffff

Reputation: 3070

Java stream concatenation after each function

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

Answers (2)

Holger
Holger

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

Rishi Saraf
Rishi Saraf

Reputation: 1812

Did you tried using Stream.onClose(). Like Stream.concat().onClose()

Upvotes: 0

Related Questions