java - 在 Stream API 中使用 AutoClosable 接口(interface)

标签 java java-8 java-stream java-io autocloseable

<分区>

今天我尝试重构这段代码,它从目录中的文件中读取 id,

Set<Long> ids = new HashSet<>();
for (String fileName : fileSystem.list("my-directory")) {
    InputStream stream = fileSystem.openInputStream(fileName);
    BufferedReader br = new BufferedReader(new InputStreamReader(stream));
    String line;
    while ((line = br.readLine()) != null) {
        ids.add(Long.valueOf(line.trim()));
    }
    br.close();
}

使用流接口(interface)

Set<Long> ids = fileSystem.list("my-directory").stream()
    .map(fileName -> fileSystem::openInputStream)
    .map(is -> new BufferedReader(new InputStreamReader(is)))
    .flatMap(BufferedReader::lines)
    .map(String::trim)
    .map(Long::valueOf)
    .collect(Collectors.toSet());

然后我发现 IO 流不会被关闭,而且我没有看到关闭它们的简单方法,因为它们是在管道内部创建的。

有什么想法吗?

upd:例子中的文件系统是HDFS,不能使用Files#lines等类似的方法。

最佳答案

一旦流的所有元素都被消耗,就可以 Hook 到流中以“关闭”资源。因此,可以通过以下修改在阅读完所有行后关闭阅读器:

.flatMap(reader -> reader.lines().onClose(() -> close(reader)))

close(AutoClosable) 处理 IOException。

作为概念证明,以下代码和输出已经过测试:

import java.util.stream.Stream;

class Test {
    public static void main(String[] args) {
        Stream.of(1, 2, 3).flatMap(i ->
                Stream.of(i, i * 2).onClose(() ->
                        System.out.println("Closed!")
                )
        ).forEach(System.out::println);
    }
}

1
2
Closed!
2
4
Closed!
3
6
Closed!

关于java - 在 Stream API 中使用 AutoClosable 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43609062/

相关文章:

java - 如果我使用 JDK 8,我的应用程序会在 android 4.0 上运行吗

java - 从使用 Java 流的员工列表中获取特定加入日期之前和之后的员工

java - 为什么使用quickfix的FIX字段为空?

java - 从大型 Set<String> 中获取重复项的最佳性能方法是什么?

grails - IntelliJ Grails 3 项目 : Unable to Run Grails project

Java 8 Hibernate Streams 标准分组按删除类型?

java - 使用字符串谓词过滤流

java - IntStream.rangeClosed(x,y) 和 IntStream.range(x,y+1) 的区别

java - Intellij IDEA - org.apache.jasper.JasperException : Unable to compile class for JSP

java - web.xml 无法正确标记 spring ServletDispatcher