1)为什么恰好第二个forEach()不起作用?确切的规则是什么?
2)如何重置流以再次在其上运行forEach?我是否总是需要创建另一个IntStream sm2 = str.chars();
之类的IntStream实例才能在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));
P.S。我知道forEach()
是终端操作,但是我了解到forEach()
不会返回流=>我无法链接调用,无法回答我的问题问题(我不需要将任何进一步的呼叫用点链接起来的情况都链接起来)。
答案 0 :(得分:1)
第一个forEach循环已清空该流。如果要重复使用forEach循环,则必须复制原始流或数据。您可以使用相同的数据创建另一个流:
IntStream sm = str.chars();
sm.forEach(System.out::println); // works
sm = str.chars();
sm.forEach(ch -> System.out.println(ch)); // works
答案 1 :(得分:0)
这是流的核心概念。流是可能是无限的数据的集合。因此,为了提高内存效率,我们无法将所有元素都保存在内存中。
流可以看作是“一个元素+获取下一个元素的方法”。因此,如果您遍历所有流,则“不知道”如何再次进行遍历,因为该信息已被丢弃。
如果您需要迭代多次,请选择另一个集合(列表?)
答案 2 :(得分:0)
总是有一个Stream::peek方法,该方法确实执行Consumer
操作并且是非终结性的。但是,正如文档所述:
此方法主要用于支持调试,您希望在其中查看元素流过管道中特定点的情况
所以我不确定这是否完全适合您。您可以在此处了解更多信息:In Java streams is peek really only for debugging?
因此,我建议仅在单个forEach
中执行任何您想执行的操作:
stream.forEach(e -> {
operation1(e);
operation2(e);
});
forEach
关闭流的原因-仅仅是因为API是这样设计的。 :)