运行以下代码示例会以以下方式结束:
“Exception in thread "main" java.lang.StackOverflowError”
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class TestStream {
public static void main(String[] args) {
Stream<String> reducedStream = IntStream.range(0, 15000)
.mapToObj(Abc::new)
.reduce(
Stream.of("Test")
, (str , abc) -> abc.process(str)
, (a , b) -> {throw new IllegalStateException();}
);
System.out.println(reducedStream.findFirst().get());
}
private static class Abc {
public Abc(int id) {
}
public Stream<String> process(Stream<String> batch) {
return batch.map(this::doNothing);
}
private String doNothing(String test) {
return test;
}
}
}
是什么导致了这个问题?这段代码的哪一部分是递归的,为什么会出现递归?
map
方法的 15000 次调用上。在内部,它必须以某种方式进行链式调用。您可以使用以下代码重现此问题,而无需使用Abc
:IntStream.range(0, 15000).boxed().reduce(Stream.of("Test"), (str , abc) -> str.map(s -> s), (a , b) -> {throw new IllegalStateException();}
- TunakiStackOverflowError
的堆栈跟踪应该揭示方法相互调用的循环。请在您的帖子中包含相关部分。StackOverflowError
的堆栈跟踪应该显示相互调用的方法循环。请在您的文章中引用相关部分。 - rgettmanStream<String> st = Stream.of("Test"); for (int i = 0; i < 15000; i++) st = st.map(s -> s); st.findFirst();
我不确定我们是否可以将其归类为一个 bug。每个 map 操作都会创建一个临时对象来包装当前的 Stream。当遍历开始时,必须经过所有这些间接操作。而且似乎太多了。 - Tunaki