【问题标题】:Repeating forEach() on the same stream - why not possible? [duplicate]在同一个流上重复 forEach() - 为什么不可能? [复制]
【发布时间】:2019-08-21 03:30:19
【问题描述】:

1) 为什么第二个 forEach() 不起作用?具体规则是什么?

2) 如何重新设置流以再次运行 forEach?我是否总是需要创建另一个 IntStream 实例,例如 IntStream sm2 = str.chars(); 才能在 sm2 (sm2.forEach(...)) 上工作,还是有办法“重置”sm?

String str = "A B C D";
IntStream sm = str.chars();

sm.forEach(System.out::println); // works

// IllegalStateException: stream has already been operated upon or closed
sm.forEach(ch -> System.out.println(ch)); 

附:我知道forEach() 是一个终端操作,但我理解它的方式是forEach() 不返回流=>我不能链接调用,这不能回答我的问题(我不'不需要链接调用任何进一步用点分隔此类调用)。

【问题讨论】:

标签: java java-8 java-stream


【解决方案1】:

流已被第一个 forEach 循环清空。如果要重复使用 forEach 循环,则必须复制原始流或数据。您可以使用相同的数据创建另一个流:

IntStream sm = str.chars();

sm.forEach(System.out::println); // works

sm = str.chars();

sm.forEach(ch -> System.out.println(ch)); // works

【讨论】:

  • 在您的回答中输入 “解决方案包括在每次需要时创建一个新流。” 不重复使用旧流。
【解决方案2】:

总是有一个Stream::peek 方法,它确实执行Consumer 操作并且是非终端的。但是,正如文档所述:

此方法的存在主要是为了支持调试,您希望在元素流过管道中的某个点时查看它们

所以我不确定这是否完全适合您。你可以在这里阅读更多:In Java streams is peek really only for debugging?

所以我建议在单个 forEach 中执行任何你想执行的操作:

stream.forEach(e -> {
    operation1(e);
    operation2(e);
});

至于forEach 关闭流的原因 - 只是因为 API 就是这样设计的。 :)

【讨论】:

    【解决方案3】:

    这是流的核心概念。流是可能是无限的数据的集合。因此,为了提高内存效率,我们不能将所有元素都保存在内存中。

    流可以看作是“一个元素+获取下一个元素的方式”。因此,如果您遍历所有流,您“不知道”如何再次迭代,因为该信息已被丢弃。

    如果需要多次迭代,那就选择另一个集合(List?)

    【讨论】:

      猜你喜欢
      • 2019-04-08
      • 2018-11-08
      • 1970-01-01
      • 2019-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多