Lambda中的Java 8 Lambda无法修改外部Lambda中的变量

假设我有一个List<String>和一个List<Transfomer>。我想将每个转换器应用于列表中的每个字符串。

使用Java 8 lambda,我可以这样做:

strings.stream().map(s -> {

for(Transformer t : transformers) {

s = t.apply(s);

}

return s;

}).forEach(System.out::println);

但是我想做更多类似的事情,但是会导致编译时错误:

strings.stream().map(s -> transformers.stream().forEach(t -> s = t.apply(s))).forEach(System.out::println);

我刚刚开始玩lambda,所以也许我只是语法不正确。

回答:

使用流执行此操作的最佳方法是使用reduce

// make a transformer that combines all of them as one

Transformer combinedTransformer =

// the stream of transformers

transformers.stream()

// combine all the transformers into one

.reduce(

// apply each of the transformers in turn

(t1, t2) -> x -> t2.apply(t1.apply(x)))

);

// the stream of strings

strings.stream()

// transform each string with the combined transformer

.map(combinedTranformer::apply);

当然,这是假定transformers非空的。如果有可能为空,则使用的两个参数重载来reduce代替就足够简单了,就像这样(假定Tranformer是一个功能接口):

// make a transformer that combines all of them as one

Transformer combinedTransformer =

// the stream of transformers

transformers.stream()

// combine all the transformers into one

.reduce(

// the no-op transformer

x -> x,

// apply each of the transformers in turn

(t1, t2) -> x -> t2.apply(t1.apply(x)))

);

// the stream of strings

strings.stream()

// transform each string with the combined transformer

.map(combinedTranformer::apply);


出现编译器错误的原因是,如错误所述,lambda表达式中使用的外部变量必须 有效地是final

;也就是说,声明它们final(如果尚未声明)不得更改程序的含义,也不得更改程序是否编译。因此,通常禁止在lambda中使用可变分配,这有充分的理由:突变会破坏并行化,而Java

8中包含lambda的主要原因之一是允许更轻松的并行编程。

一般来说,只要您想以某种方式“总结”结果,reduce(无论是三个重载中的任何一个)都是您的首选方法。学习如何使用mapfilterreduce,和flatMap有工作的时候实际上是非常重要Stream秒。

以上是 Lambda中的Java 8 Lambda无法修改外部Lambda中的变量 的全部内容, 来源链接: utcz.com/qa/418776.html

回到顶部