【问题标题】:Java 8 flatMapped stream closed in try-with-resources block [duplicate]Java 8 flatMapped 流在 try-with-resources 块中关闭 [重复]
【发布时间】:2020-04-30 23:20:31
【问题描述】:

我有两种方法可以返回列表中字符串的长度,如下所示;

    private Stream<Integer> method1(List<String> list) {
        try (final Stream<String> myStream = list.stream()) {
            return myStream.map(String::length);
        }
    }

    private Stream<Integer> method2(List<String> list) {
        try (final Stream<String> myStream = list.stream()) {
            return myStream.map(String::length).flatMap(Stream::of);
        }
    }

当我尝试使用任一方法的结果流时;

    List<Integer> collect = method1(list).collect(Collectors.toList());

    List<Integer> collect = method2(list).collect(Collectors.toList());

我明白了

    Exception in thread "main" java.lang.IllegalStateException: source already consumed or closed

现在我知道在 try-with-resources 块中使用流并不常见。但在我的真实代码中,我在 try-with-resources 中使用Stream&lt;Path&gt; paths = Files.walk(Path.of(myPath))。在Files.walk(..) 方法的文档中它说

此方法必须在 try-with-resources 语句或类似的控制结构中使用,以确保在流的操作完成后立即关闭流的打开目录。

上面的代码只是说明问题的一个例子。

我的问题是,尽管我使用 mapflatMap 返回一个新流,但为什么我的流已关闭。我期望这两种方法返回新的Stream 实例,因此只有myStream 被关闭而不是map 操作返回的实例,我错了吗?我对 monad 的理解很模糊,但 mapflatMap 方法的行为是否意味着 Stream 不是真正的 monad?

【问题讨论】:

  • 不要使用try-with-resources,让调用者处理流的关闭
  • 我在我的方法中为我的流使用 try-with-resources。然后我希望这个方法创建另一个流供方法调用者使用。

标签: java java-8 functional-programming java-stream monads


【解决方案1】:

stream 将在 try 块完成后关闭。

因为Stream&lt;T&gt; 扩展了BaseStream&lt;T, Stream&lt;T&gt;&gt;BaseStream 扩展了AutoCloseable

为什么我在block中创建的Stream实例也关闭了

因为在块中创建的新Stream 实例是链式嵌套的 myStream 的流,并在 myStream(外部流)关闭后立即关闭。您可以使用onClose 进行验证,如下所示,

privat Stream<Integer> method1(List<String> list) {
    try (final Stream<String> myStream = list.stream()) {
        Stream<Integer> integerStream = myStream.onClose(r)
                .map(String::length).onClose(r1);
        return integerStream;
    }
}
Runnable r = ()->{
    System.out.println("closed main stream...");
};
Runnable r1 = ()->{
    System.out.println("closed map stream...");
};

【讨论】:

  • 我知道 try-with-resources 中的流将被关闭。我在问为什么我在块中创建的Stream 实例也关闭了。
  • @Taha 更新了答案。用上面的评论改写你的问题,我会投票支持重新提出这个问题。
  • 在那条评论之前我已经做过了。不知何故,我无法提及您的用户名。
  • @Taha 只有一个流。只有不同的 Stream 实例来支持像 stream.map(...).filter(...).distinct() 这样的流畅构建,而每次链接操作时,您可能会得到一个表示流的新实例,这会使旧实例无效。由于只有一个流,所以只有一个“关闭”状态。
  • 大家好,我想问一下这个案子。在我的程序中,当我不尝试使用资源时,它会引发 No file descriptors available 但是当我尝试使用资源时,我遇到了“源已经消耗或关闭”的问题。如果我喜欢这个解决方案,“integerStream”会引发没有可用的文件描述符。 Tks
猜你喜欢
  • 2018-08-15
  • 1970-01-01
  • 2019-03-12
  • 2014-12-18
  • 2021-01-28
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
相关资源
最近更新 更多