微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

forEach java 8 为大数据集抛出 StackOverflow 错误

如何解决forEach java 8 为大数据集抛出 StackOverflow 错误

我正在尝试类似 -

        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.StackOverflowError: null
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) ~[?:1.8.0_275]
    at java.util.stream.ReferencePipeline$7$1.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 实现,它知道它想要执行 flatMap在两个值上, ... ,其中一个是空的 Stream 实现。

在内部,它们被实现为彼此的包装器,并在必要时相互调用。

由于每个 Stream 实现都需要调用下一个实现,并且该链有数千个对象深,因此您至少需要如此深的堆栈才能完全执行它(实际上可能需要多个这个数字,因为堆栈中可能还有一些辅助方法/中间方法)。

在您的工作代码中,您只有一个 Stream 包含要迭代的 Stream 对象列表。因此调用深度非常有限:外部流一个接一个地委托给内部流。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。