Java 8 Stream在地图内使用地图时关闭

Bob*_*Bob 4 java java-8 java-stream

我想加入两个流.我遇到了我的流关闭的问题,我不明白为什么.难道没有人请向我解释为什么会发生以下情况.

下面的代码不起作用.我在flatMap函数上得到一个例外,该流已经关闭了.

private Stream<KeyValuePair<T, U>> joinStreams(Stream<T> first, Stream<U> second) {
        return 
                first
                    .map(x -> second
                                .map(y -> new KeyValuePair<T, U>(x, y))
                        )
                    .flatMap(x -> x);       
    }
Run Code Online (Sandbox Code Playgroud)

当我第一次从第二个流中收集一个列表,然后从该列表中获取一个流时,它确实有效.请参阅下面的示例.

private Stream<KeyValuePair<T, U>> joinStreams(Stream<T> first, Stream<U> second) {
    List<U> secondList = second.collect(Collectors.toList());
    return 
            first
                .map(x -> secondList.stream()
                            .map(y -> new KeyValuePair<T, U>(x, y))
                    )
                .flatMap(x -> x);       
}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么会这样.有人可以解释一下吗?

编辑:

调用此函数的代码示例.

List<Integer> numbers1 = Arrays.asList(1, 2);
List<Integer> numbers2 = Arrays.asList(3, 4);

List<KeyValuePair<Integer, Integer>> combined = joinStreams(numbers1.stream(), numbers2.stream())
                                                    .collect(Collectors.toList());

// Expected result
// 1 3
// 1 4
// 2 3
// 2 4
Run Code Online (Sandbox Code Playgroud)

Era*_*ran 5

问题是你的代码试图处理第二Stream次(第一次的每个元素一次Stream).A Stream只能处理一次,就像Iterator只能迭代一次底层类的元素一样.

如果你的第一个Stream只有一个元素,代码就可以工作,因为第二个元素Stream只会被处理一次.

在有效的代码中,为第一个元素的每个元素生成一个new Stream(from secondList)Stream,因此每个Stream元素都处理一次,无论第一个元素有多少元素Stream.

  • @Bob,或者你不能接受`Stream <U>`,而是'Supplier <Stream <U >>`参数并使用`supplier.get()`.这样你就不会受限于从集合创建的流,像`joinStreams(stream1,() - > IntStream.range(0,100).boxed())这样的代码也可以.对于集合源,你需要写成`joinStreams(stream1,numbers2 :: stream)` (3认同)
  • @Bob你可以传递给你的方法2 Lists(或Collections)而不是两个Streams.然后,您的方法将为第一个List创建一个Stream,为第二个List创建所需的Streams,并返回已连接的Stream. (2认同)