ストリーム パイプライン中に多くのファイルを開くこのコードを実行すると:
public static void main(String[] args) throws IOException {
Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
100, (path, attr) -> path.toString().endsWith(".html"))
.map(file -> runtimizeException(() -> Files.lines(file, StandardCharsets.ISO_8859_1)))
.map(Stream::count)
.forEachOrdered(System.out::println);
}
例外があります:
java.nio.file.FileSystemException: /long/file/name: Too many open files
問題はStream.count
、ストリームのトラバースが完了したときにストリームを閉じないことです。しかし、それが端末操作であることを考えると、なぜそうすべきではないのかわかりません。reduce
やなどの他の端末操作についても同様forEach
です。flatMap
一方、それが構成するストリームを閉じます。
ドキュメントには、必要に応じて try-with-resouces-statement を使用してストリームを閉じるように指示されています。私の場合、count
行を次のように置き換えることができます。
.map(s -> { long c = s.count(); s.close(); return c; } )
しかし、これはうるさくて醜く、大規模で複雑なパイプラインを使用する場合には、非常に不便な場合があります。
だから私の質問は次のとおりです。
- ターミナル操作が作業中のストリームを閉じるようにストリームが設計されなかったのはなぜですか? これにより、IO ストリームでより適切に機能するようになります。
- パイプラインで IO ストリームを閉じるための最適なソリューションは何ですか?
runtimizeException
チェックされた例外をRuntimeException
s にラップするメソッドです。