相关疑难解决方法(0)

为什么flatMap()之后的filter()在Java流中"不完全"懒惰?

我有以下示例代码:

System.out.println(
       "Result: " +
        Stream.of(1, 2, 3)
                .filter(i -> {
                    System.out.println(i);
                    return true;
                })
                .findFirst()
                .get()
);
System.out.println("-----------");
System.out.println(
       "Result: " +
        Stream.of(1, 2, 3)
                .flatMap(i -> Stream.of(i - 1, i, i + 1))
                .flatMap(i -> Stream.of(i - 1, i, i + 1))
                .filter(i -> {
                    System.out.println(i);
                    return true;
                })
                .findFirst()
                .get()
);
Run Code Online (Sandbox Code Playgroud)

输出如下:

1
Result: 1
-----------
-1
0
1
0
1
2
1
2
3
Result: -1
Run Code Online (Sandbox Code Playgroud)

从这里我看到,在第一种情况下stream真的表现得懒惰 - 我们使用findFirst()所以一旦我们有第一个元素我们的过滤lambda没有被调用.然而,在使用flatMaps的第二种情况下,我们看到尽管找到满足过滤条件的第一个元素(它只是任何第一个元素,因为lambda总是返回true),流的其他内容仍然通过过滤函数被馈送.

我试图理解为什么它表现得像这样,而不是在第一个元素计算后放弃,如第一种情况.任何有用的信息将不胜感激.

java lambda java-8 java-stream

70
推荐指数
4
解决办法
6190
查看次数

为什么Files.lines(和类似的Streams)不会自动关闭?

Stream的javadoc说明:

Streams有一个BaseStream.close()方法并实现AutoCloseable,但几乎所有的流实例实际上都不需要在使用后关闭.通常,只有源为IO通道的流(例如Files.lines(Path,Charset)返回的流)才需要关闭.大多数流都由集合,数组或生成函数支持,不需要特殊的资源管理.(如果流确实需要关闭,则可以在try-with-resources语句中将其声明为资源.)

因此,绝大多数情况下,人们可以在单行中使用Streams,collection.stream().forEach(System.out::println);但是对于Files.lines和其他资源支持的流,必须使用try-with-resources语句或泄漏资源.

这让我觉得容易出错并且不必要.因为Streams只能迭代一次,所以在我看来,没有一个迭代后Files.lines不应该关闭输出的情况,因此实现应该只是在任何终端操作结束时隐式调用close .我错了吗?

java stream resource-leak java-8 java-stream

48
推荐指数
3
解决办法
9075
查看次数

stream.spliterator()是否关闭了流?

是否stream.spliterator()隐式关闭stream,或者之后是否需要明确关闭它?

Stream<String> stream = Stream.of("a", "b", "c");
Spliterator<T> spliterator = stream.spliterator();
// Some low lever operation with the spliterator
stream.close(); // do we need to close?
Run Code Online (Sandbox Code Playgroud)

乍一看,似乎该.spliterator()方法关闭了stream,但没有调用stream.close().至少如果我在.spliterator()调用方法后立即将其关闭,似乎不会影响分裂器操作.

Stream<String> stream = Stream.of("a", "b", "c").limit(2);
Spliterator<T> spliterator = stream.spliterator();
stream.close();
// Some low lever operation with the spliterator
Run Code Online (Sandbox Code Playgroud)

这个问题可以扩展到其他stream方法,例如,.findAny().

stream.findAny() // Can I assume that I don't need to close the stream?
stream.onClose(() -> System.out.println("hi!")).findAny()`
// …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream spliterator

15
推荐指数
2
解决办法
758
查看次数

我应该总是关闭BufferedReader吗?

这是一行将文件读入List:

List<String> lines =
    new BufferedReader(
        new InputStreamReader(classLoader.getResourceAsStream(fileName)))
            .lines()
            .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

这是正确的还是应该将BufferedReader变量分配给变量以便以后关闭它?

java bufferedreader

9
推荐指数
2
解决办法
1071
查看次数

为什么在try-with-resources中获取`Stream <String>`时BufferedReader没有关闭?

Stream在try-with-resources中使用a 时,应该关闭阅读器.

鉴于这种:

try(Stream<String> lines = new BufferedReader(reader).lines()) {
            return lines.map(it -> trim ? it.trim() : it)
                    .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

......读者没有被关闭?

此测试失败:

    AtomicBoolean closed = new AtomicBoolean(false);

    Reader r = new StringReader("  Line1 \n Line2") {

                @Override
                public void close() {
                    super.close();
                    closed.set(true);
                }

            };

    try(Stream<String> lines = new BufferedReader(r).lines()) {
            lines.map(it -> trim ? it.trim() : it)
                    .collect(Collectors.toList());
    }

    assertTrue("Reader was not closed.",closed.get());
Run Code Online (Sandbox Code Playgroud)

java java-8 try-with-resources java-stream autocloseable

3
推荐指数
1
解决办法
685
查看次数