在try-with-resources中使用Stream
时,应关闭阅读器。
鉴于此:
try(Stream<String> lines = new BufferedReader(reader).lines()) {
return lines.map(it -> trim ? it.trim() : it)
.collect(Collectors.toList());
}
......读者没有被关闭?
此测试失败:
AtomicBoolean closed = new AtomicBoolean(false);
Reader r = new StringReader(" Line1 \n Line2") {
@Override
public void close() {
super.close();
closed.set(true);
}
};
try(Stream<String> lines = new BufferedReader(r).lines()) {
lines.map(it -> trim ? it.trim() : it)
.collect(Collectors.toList());
}
assertTrue("Reader was not closed.",closed.get());
答案 0 :(得分:8)
我实际上并没有使用try-resources语法。希望我的回答有道理。
根据我的理解,自动关闭正在关闭声明中声明的资源,没有别的。
因此,try(Stream<String> lines = new BufferedReader(r).lines()) {
只是关闭lines
,而不是那个没有分配变量的缓冲读者。
如果你打算关闭缓冲的阅读器和流(你真的需要关闭流吗?),iirc,你可以在try语句中有多行:
try (BufferedReader br = new BufferedReader(r);
Stream<String> lines = br.lines()) {
//....
}
这样的事情。 (没有尝试编译,希望它有效:P)
答案 1 :(得分:0)
虽然这不是您问题的即时答案,但它可以确保之后关闭所有资源。
受到 Guava 的 CharSource.lines()
实现的启发,该实现使用关闭处理程序 Stream.onClose(Runnable)
在处理的流关闭时关闭相应的 BufferedReader 并且
Stream.flatMap(...)
的特性(感谢这个 trick)
在其内容放入后调用 BaseStream.close()
这个流。
您可以获得在终端操作后自动关闭的行流。
Stream<String> lines = lines(reader);
// ..
Stream<String> lines(Reader reader) {
BufferedReader br = new BufferedReader(reader);
Stream<String> lines = br.lines()
.onClose(() -> {
try {
br.close();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
return Stream.of(lines).flatMap(s -> s); // Autocloseable exploit of Stream.flatMap()
}