使用流StreamSupplier

时间:2018-07-18 13:25:38

标签: java arrays java-8 java-stream

我正在使用以下代码重用Stream,但得到

  

java.lang.IllegalStateException:流已被操作或关闭

代码

public static void main(String[] args) {

    try {
        String[] array = { "a", "b", "c", "d", "e" };
        Stream<String> ss = Stream.of(array);
        Supplier<Stream<String>> streamSupplier = () -> ss;

        long count = streamSupplier.get().count();
        // get new stream
        streamSupplier.get().forEach(x -> System.out.println(x));

        // get another new stream

        System.out.println(count);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4 个答案:

答案 0 :(得分:4)

不要将Stream.of(array)分配给中间变量,只需直接在Supplier中将其返回即可:

Supplier<Stream<String>> streamSupplier = () -> Stream.of(array);

这是因为以前,您在调用supplier.get()时总是会提供相同的 reference ,但实际上您想返回一个新的Stream

也正如@Eugene建议的那样,最好使用Arrays.stream()而不是Stream.of()。后者是varargs方法,但仅委托给前者。


此外,您可以使用Stream.peek()方法来简化当前的方法:

long count = Arrays.stream(array)
    .peek(System.out::println)
    .count();

答案 1 :(得分:4)

Stream::countterminal操作,它将关闭Stream,因此无法继续处理任何管道。

您先创建Stream<String>,然后再将其放入Supplier。如果您希望供应商在每次调用时提供一个新的Stream女巫,请直接在Stream<String>中创建Supplier

Supplier<Stream<String>> streamSupplier = () -> Stream.of(array);

然后streamSupplier.get()将始终与新的Stream<Stream>一起使用。


但是,您可以使用Stream::peek达到相同的结果,该结果与Stream::forEach的工作原理相同,不同的是它不会关闭Stream而是返回相同的未修改的(@ Lino更快)。

long count = streamSupplier.get().peek(System.out::println).count();

答案 2 :(得分:1)

您遇到的异常是适当的,它告诉您需要研究的内容。来自Java 8 Stream class

  

应该对流进行操作(调用中间或终端   流操作)。例如,这排除了“分叉”   流,其中相同的源提供两个或多个管道,或者   同一流的多个遍历。流实现可以   如果检测到流正在被抛出,则抛出IllegalStateException   重用。但是,由于某些流操作可能会返回它们   接收者而不是新的流对象,则可能无法   检测所有情况下的重用。

答案 3 :(得分:0)

您仍在重复使用同一流。将<local:RepeaterView x:Name="approvalsStack" ItemsSource="{Binding Approvals}"> <local:RepeaterView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Grid.Column="0" Text="{Binding FullName}"/> <Label Grid.Column="1" Text="{Binding Decision}"/> <Label Grid.Column="2" Text="{Binding DecisionDate}"/> </Grid> <StackLayout> <BoxView HeightRequest="1" Color="Gray" HorizontalOptions="FillAndExpand"/> </StackLayout> </StackLayout> </ViewCell> </DataTemplate> </local:RepeaterView.ItemTemplate> </local:RepeaterView> 移到供应商内部,而不是外部。