java - Java 8 flatMapped 流在 try-with-resources 块中关闭
问题描述
我有两种方法可以返回列表中字符串的长度,如下所示;
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 块中使用流并不常见。但是在我的真实代码中,我Stream<Path> paths = Files.walk(Path.of(myPath))
在 try-with-resources 中使用。在Files.walk(..)
方法的文档中它说
此方法必须在 try-with-resources 语句或类似的控制结构中使用,以确保在流的操作完成后立即关闭流的打开目录。
上面的代码只是说明问题的一个例子。
我的问题是为什么我的流被关闭了,尽管我使用map
并flatMap
返回一个新的流。我是否错误地期望这两种方法返回新Stream
实例,因此只有myStream
关闭而不是map
操作返回的实例?map
我对单子有一个模糊的理解,但是flatMap
方法的行为意味着Stream
不是真正的单子吗?
解决方案
块完成stream
后将关闭。try
因为Stream<T>
延伸BaseStream<T, Stream<T>>
和BaseStream
延伸AutoCloseable
为什么我在块中创建的 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...");
};
推荐阅读
- php - #laravel 419 错误出现提交任何形式此问题仅在其他托管应用程序上的 GoDaddy 托管上工作正常
- django - 如何在 Django REST Framework API 的 OneToOne 序列化器字段上允许空白字段?
- python-3.x - 这是检查最多 9 个泛数字的正确方法吗?
- r - R 扫描函数如何与多维数组一起工作?
- reactjs - Redux - 从后端获取初始状态 - 这是正确的方法吗?
- swift - 在用户输入上添加结构
- python-3.x - Python3:找到除以10后余数最大的数(第二个答案的while循环中的一些错误)
- python - 重复for循环读取文件直到满足条件
- git - 离线时如何快进origin/master?
- django - 如何使用 Postman 使用带有参数的 Django api?