Java for循环与Stream .forEach有什么区别

时间:2019-07-04 19:31:04

标签: java lambda

下面的for循环生成lambda表达式的集合。

 Callable<String>[] tasks = new Callable[messageCount];
 for (int i = 0; i < count; i++) {
   tasks[i] = () -> msg;
 }

对流forEach进行相同的尝试会产生空值。

 Arrays.stream(tasks).forEach(t -> {
   t = () -> message;
 });

我想念什么?我该如何解决?

2 个答案:

答案 0 :(得分:2)

在第一个代码示例中,您正在将lambda表达式() -> msg分配给tasks数组的每个元素。

但是,在第二个示例中,您正在将lambda表达式() -> msg分配给类型为t临时变量Callable<String>Stream#forEach的目的是将流中的元素传递给以某种方式使用元素的消费者。如果您以某种方式分配给使用者的参数,则流的源将不会反映出来。这样的操作甚至可能没有任何意义:

IntStream.range(1,10).filter((x) -> (x % 2 == 0)).forEach((x) -> {++x;});

这与Java流的一般主题有关:它们是用于生成,转换,过滤和使用数据的单向管道。由于数据从Arrays.stream供应商处流动,因此只能沿一个方向流入消费者(forEach);下游所做的更改不会传播回上游。

答案 1 :(得分:0)

您的流代码等效于以下for循环:

for (Callable<String> t : tasks) {
    t = () -> message;
}

其本身等同于:

for (int i = 0; i < tasks.length; i++) {
    Callable<String> t = tasks[i];
    t = () -> msg;
}

更改t的值不会更改tasks[i]的值。

要创建长度为messageCount且元素为lambda表达式的数组,请使用流式传输:

Callable<String>[] tasks = IntStream.range(0, messageCount)
                                    .mapToObj(i -> (Callable<String>) () -> msg)
                                    .toArray(Callable[]::new);