当我们使用Stream.concat
连接流时,是否可以在流结束时运行一个函数?
例如
我正在使用 Files.lines
从多个文件创建流。现在,每当一个文件被完全读取时,我就需要将其删除。
最佳答案
通过Stream.concat
组成的流的关闭处理程序在结果流关闭时执行。请注意,关闭处理程序通常要求使用流的代码关闭流,例如
try(Stream<String> s=Stream.concat(Files.lines(path1), Files.lines(path2))) {
s.forEach(System.out::println);
}
正确关闭和
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);
}
用于随后删除文件。但在这种情况下,结果流的关闭处理程序将调用源流的关闭处理程序,因此这不会在使用后立即删除文件,而是在整个操作之后删除,因此与
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);
}
如果你想及时删除文件,你必须使用flatMap
。无论“外”流是否关闭,子流在使用后都会立即关闭:
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);
<小时/>
为了证明差异,
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);
}
将打印
foo
bar
foo closed
bar closed
而
Stream.of("foo", "bar")
.flatMap(x -> Stream.of(x).onClose(()->System.out.println(x+" closed")) )
.forEach(System.out::println);
将打印
foo
foo closed
bar
bar closed
关于每个函数之后的 Java 流串联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40629620/