使用JUnit
和Stream
我收到以下错误消息:
java.lang.IllegalStateException: stream has already been operated upon or closed
我做了一项研究,很清楚不可能重用流
但是根据这篇文章:
使用Supplier
可以解决此问题。
所以我目前的代码如下:
try (Stream<String> stream = Files.lines(Paths.get(fileName)) ) {
Supplier<Stream<String>> supplier = () -> stream;
logger.info("A");
logger.info("ABC {}", supplier.get().findFirst().get());
logger.info("B");
logger.info("XYZ {}", supplier.get().skip(1050).findFirst().get());
logger.info("C");
assertThat(supplier.get().count(), is(1051));
}
catch (IOException e) {
logger.error("{}", e.getMessage());
}
如何看待我使用supplier.get()
使用Stream
(根据教程),但@Test
打印直到 B ,因此@Test
在supplier.get().skip(1050).findFirst().get()
失败,但仍然会生成相同的错误消息。
我的代码和教程之间的独特区别,mime通过文件工作,教程围绕数组工作。
编辑工作没有任何问题?
α
我做了以下版本(根据Eugene的代码段)
try (Stream<String> stream = Files.lines(Paths.get(fileName)) ) {
Supplier<Stream<String>> supplier = () -> stream.collect(Collectors.toList()).stream();
logger.info("A");
logger.info("ABC {}", supplier.get().findFirst().get());
logger.info("B");
logger.info("XYZ {}", supplier.get().skip(1050).findFirst().get());
logger.info("C");
assertThat(supplier.get().count(), is(1051));
}
相同的错误消息。
答案 0 :(得分:7)
Supplier
并不神奇,您仍然需要始终从该供应商提供 new Stream 。
所以你可以这样做:
Supplier<Stream<String>> supplier = () -> Files.lines(Paths.get(fileName));
但这意味着要一直读取文件。您可以将所有行读入单个List
,将其存储在内存中,并将stream
存储在内存中。
List<String> allLines = Files.readAllLines(Paths.get(fileName));
Supplier<Stream<String>> supplier = () -> allLines.stream();
请注意,即使您链接的教程也会返回一个新的Stream,通过Stream.of
创建,如下所示:
Supplier<Stream<String>> streamSupplier = () -> Stream.of(array);
答案 1 :(得分:3)
这是因为您的供应商始终提供Stream
的相同实例,并且您已使用findFirst()
使用它。然后你尝试用findFirst()
再次使用它,这是不允许的。
在本教程中,每次都会创建一个新流。在您的情况下,您必须在供应商内部调用Files.lines()
才能使其正常工作,但这意味着您每次都会重新阅读该文件。