简体   繁体   English

java 懒惰 stream 构造中的问题

[英]Issue in java lazy stream construction

I was looking at this link for lazy stream construction and tried using it for one of my cases.我正在查看链接以了解惰性 stream 构造,并尝试将其用于我的一个案例。

My primary stream has some operations that are needed to be done on Stream.onClose() .我的主要 stream 有一些需要在Stream.onClose()上完成的操作。

In my custom logic, I use Iterator from Stream.iterator() for stream processing.在我的自定义逻辑中,我使用来自Stream.iterator()的迭代器进行 stream 处理。

This worked fine consuming the actual Stream.这很好地消耗了实际的 Stream。 But, when I used Stream.flatMap() for constructing a lazy stream, onClose function gets called when I start iterating, which in-turn creates problems for me.但是,当我使用Stream.flatMap()来构造一个惰性 stream 时, onClose function 在我开始迭代时被调用,这反过来又给我带来了问题。

I tried this in zulu-opendjk 1.8.0_222 and 13. I am facing this exception in both the environments.我在 zulu-opendjk 1.8.0_222 和 13 中尝试过这个。我在两种环境中都面临这个异常。

在此处输入图像描述

You can reproduce the problem with the below code.您可以使用以下代码重现该问题。

import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class TestStreamIterator
{
    public static void main(String args[])
    {
        Stream<String> stream1 = getStream();
        stream1.iterator().forEachRemaining(System.out::println);

        Stream<String> stream2 = Stream.of(1).flatMap(integer -> getStream());
        stream2.iterator().forEachRemaining(System.out::println);
    }

    private static Stream<String> getStream()
    {
        List<String> values = Arrays.asList("a", "b", "c");

        MyIterator iterator = new MyIterator(values);
        Stream<String> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.NONNULL | Spliterator.IMMUTABLE), false).onClose(iterator::close);

        return stream;
    }

    private static class MyIterator implements Iterator<String>, AutoCloseable
    {
        private Iterator<String> iterator;

        public MyIterator(List<String> values)
        {
            iterator = values.iterator();
        }

        @Override
        public boolean hasNext()
        {
            return iterator.hasNext();
        }

        @Override
        public String next()
        {
            return iterator.next();
        }

        @Override
        public void close()
        {
            throw new IllegalStateException("Should not come here");
        }
    }
}

My understating is, when using flatMap ;我的低估是,使用flatMap时; close method of Stream.of(1) only should be called.只应调用Stream.of(1)close方法。 Not of the stream created inside flatMap function.不是在flatMap function 中创建的 stream。

I was expecting the onClose function to be invoked only when the stream is closed.我期待onClose function 只有在 stream 关闭时才会被调用。 But, I am not sure where the stream is getting closed.但是,我不确定 stream 在哪里关闭。

Any help on solving this case would also be helpful.解决此案的任何帮助也会有所帮助。

When you call flatMap(integer -> getStream()) here:当您在这里调用flatMap(integer -> getStream())时:

Stream<String> stream2 = Stream.of(1).flatMap(integer -> getStream());
stream2.iterator().forEachRemaining(System.out::println);

You are calling this method:您正在调用此方法:

Iterator迭代器

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream .每个映射的 stream 在其内容已放入此 stream 后关闭 (If a mapped stream is null an empty stream is used, instead.) (如果映射的 stream 是 null 则使用空的 stream。)

So as the documentation says, the mapped stream you pass into this method (from getStream() which is a Stream over a MyIterator ) will be closed, which it is, then (as defined in onClose of that Stream) it calls MyIterator.close() which throws the exception.因此,正如文档所述,映射的 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 您传递给此方法(来自getStream() ,它是 MyIterator 上的MyIterator )将被关闭,它就是这样,然后(如该 Stream 的onClose中定义)它调用MyIterator.close()引发异常。


Addressing your comment since you don't seem to follow:解决您的评论,因为您似乎没有关注:

Stream<String> stream2 = Stream.of(1).flatMap(integer -> getStream());

Creates a stream that will lazily map to the contents of a sub-stream when you read it.创建一个 stream ,当您阅读它时,它将延迟 map 到子流的内容。 When that sub-stream is loaded into the main stream the sub-stream will be closed.当该子流加载到主 stream 时,子流将被关闭。

stream2.iterator().forEachRemaining(System.out::println);

You read from the main stream, which maps to the sub-stream, which reads all the sub-stream then closes the sub-stream which then calls Stream.onClose() which calls MyIterator.close()您从主 stream 读取,它映射到子流,读取所有子流然后关闭子流,然后调用Stream.onClose()调用MyIterator.close()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM