forEach java 8 为大数据集抛出 StackOverflow 错误
forEach java 8 throws StackOverflow Error for big dataset
我正在尝试 -
Stream<String> wat = Stream.empty();
for (long i=0;i<10000000L;i++) {
Stream<String> yaya = Stream.of("This iis a very biig string lsjdflkjkj lkasdjf lkjdsal");
wat = Stream.of(wat, yaya).flatMap(Function.identity());
}
AtomicInteger i= new AtomicInteger();
wat.forEach(st-> {
i.incrementAndGet();
});
System.out.println(i);
以上抛出堆栈溢出错误-
java.lang.WhosebugError: null
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) ~[?:1.8.0_275]
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:272) ~[?:1.8.0_275]
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[?:1.8.0_275]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[?:1.8.0_275]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[?:1.8.0_275]
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[?:1.8.0_275]
经过几次尝试和尝试,我能够通过使用流列表和使用嵌套 for 循环来解决这个问题 -
List<Stream<String>> listOfStream = new ArrayList<>();
for (long i=0;i<10000000L;i++) {
Stream<String> yaya = Stream.of("This iis a very biig string lsjdflkjkj lkasdjf lkjdsal");
listOfStream.add(yaya);
}
AtomicInteger i= new AtomicInteger();
listOfStream.forEach(st ->
st.forEach(sm -> {
i.incrementAndGet();
})
);
System.out.println(i);
此代码不会引发任何堆栈溢出问题。我试图查找各种文章,但无法理解为什么这是有效的而前者失败了。请帮忙。
您在初始 for
循环中所做的是构建一个非常大的对象树来描述您想要实现的目标。
将有一个 Stream
实现知道它想要对两个值执行 flatMap
,其中之一将是一个 Stream
实现知道它想要对两个值执行 flatMap
,其中一个将是一个 Stream
实现,它知道它想要对两个值执行 flatMap
,其中一个将是 Stream
] 知道它想要对两个值执行 flatMap
的实现,其中之一将是一个 Stream
实现,它知道它想要对两个值执行 flatMap
,其中之一这将是一个 Stream
实现,它知道它想要对两个值执行 flatMap
,其中之一将是一个 Stream
实现,它知道它想要执行 [=12] =] 在两个值上,...,其中一个是空 Stream
实现。
在内部,它们被实现为相互包装并在必要时相互调用。
由于每个 Stream
实现都需要调用下一个并且该链有数千个对象深度,因此您至少需要这么深的堆栈才能完全执行它(实际上可能该数字的倍数,因为堆栈中可能还有一些 helper/intermediary 方法)。
在您的工作代码中,您只有一个 Stream
包含要迭代的 Stream
个对象的列表。所以调用深度非常有限:外层流一个接一个地委托给内层流。
我正在尝试 -
Stream<String> wat = Stream.empty();
for (long i=0;i<10000000L;i++) {
Stream<String> yaya = Stream.of("This iis a very biig string lsjdflkjkj lkasdjf lkjdsal");
wat = Stream.of(wat, yaya).flatMap(Function.identity());
}
AtomicInteger i= new AtomicInteger();
wat.forEach(st-> {
i.incrementAndGet();
});
System.out.println(i);
以上抛出堆栈溢出错误-
java.lang.WhosebugError: null
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) ~[?:1.8.0_275]
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:272) ~[?:1.8.0_275]
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[?:1.8.0_275]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[?:1.8.0_275]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[?:1.8.0_275]
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[?:1.8.0_275]
经过几次尝试和尝试,我能够通过使用流列表和使用嵌套 for 循环来解决这个问题 -
List<Stream<String>> listOfStream = new ArrayList<>();
for (long i=0;i<10000000L;i++) {
Stream<String> yaya = Stream.of("This iis a very biig string lsjdflkjkj lkasdjf lkjdsal");
listOfStream.add(yaya);
}
AtomicInteger i= new AtomicInteger();
listOfStream.forEach(st ->
st.forEach(sm -> {
i.incrementAndGet();
})
);
System.out.println(i);
此代码不会引发任何堆栈溢出问题。我试图查找各种文章,但无法理解为什么这是有效的而前者失败了。请帮忙。
您在初始 for
循环中所做的是构建一个非常大的对象树来描述您想要实现的目标。
将有一个 Stream
实现知道它想要对两个值执行 flatMap
,其中之一将是一个 Stream
实现知道它想要对两个值执行 flatMap
,其中一个将是一个 Stream
实现,它知道它想要对两个值执行 flatMap
,其中一个将是 Stream
] 知道它想要对两个值执行 flatMap
的实现,其中之一将是一个 Stream
实现,它知道它想要对两个值执行 flatMap
,其中之一这将是一个 Stream
实现,它知道它想要对两个值执行 flatMap
,其中之一将是一个 Stream
实现,它知道它想要执行 [=12] =] 在两个值上,...,其中一个是空 Stream
实现。
在内部,它们被实现为相互包装并在必要时相互调用。
由于每个 Stream
实现都需要调用下一个并且该链有数千个对象深度,因此您至少需要这么深的堆栈才能完全执行它(实际上可能该数字的倍数,因为堆栈中可能还有一些 helper/intermediary 方法)。
在您的工作代码中,您只有一个 Stream
包含要迭代的 Stream
个对象的列表。所以调用深度非常有限:外层流一个接一个地委托给内层流。