如何在执行一个操作后重用Stream

时间:2016-08-18 10:51:26

标签: java java-8 java-stream

我希望使用相同的String两次找出以特定字符开头的Stream,但第二个Stream操作会抛出异常。如何重新使用Stream

public static void main(String[] args) {
    Stream<String> stream = Stream.of("abc", "aef", "bcd", "bef", "crf");
    stream.filter(s -> s.startsWith("a")).forEach(System.out::println);;
    stream.filter(s -> s.startsWith("b")).forEach(System.out::println);;
}

异常

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.util.stream.AbstractPipeline.<init>(Unknown Source)
    at java.util.stream.ReferencePipeline.<init>(Unknown Source)
    at java.util.stream.ReferencePipeline$StatelessOp.<init>(Unknown Source)
    at java.util.stream.ReferencePipeline$2.<init>(Unknown Source)
    at java.util.stream.ReferencePipeline.filter(Unknown Source)
    at StreamExp.main(StreamExp.java:13)

3 个答案:

答案 0 :(得分:2)

您无法在同一forEach两次执行Stream等终端操作。

您还有其他选择。例如,您可以生成Map<Character,List<String>>,其中输入String按其第一个字符分组:

Map<Character,List<String>> groups = 
    Stream.of("abc", "aef", "bcd", "bef", "crf")
          .collect(Collectors.groupingBy(s->s.charAt(0)));

这将产生以下Map

{a=[abc, aef], b=[bcd, bef], c=[crf]}

答案 1 :(得分:1)

使用逻辑OR将流组合成一个流:

public static void main(String[] args) {
        Stream<String> stream = Stream.of("abc", "aef", "bcd", "bef", "crf");
        stream.filter(s -> s.startsWith("a") || s.startsWith("b")).forEach(System.out::println);
}

答案 2 :(得分:0)

当您呼叫任何终端操作时,流已关闭,您可以使用流供应商构建新流

Supplier<Stream<String>> streamSupplier =
            () -> Stream.of("abc", "aef", "bcd", "bef", "crf");

            streamSupplier.get().filter(s -> s.startsWith("a")).forEach(System.out::println);
            streamSupplier.get().filter(s -> s.startsWith("b")).forEach(System.out::println);