当前位置: 首页 > 知识库问答 >
问题:

lambda内的Java 8 lambda不能从外部lambda修改变量

皇甫聪
2023-03-14

假设我有一个列表 和一个列表 。我想将每个变压器应用于列表中的每个字符串

使用Java8 lambdas,我可以这样做:

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);

我刚刚开始玩lambdas,所以也许我只是没有正确的语法。

共有1个答案

令狐宣
2023-03-14

使用流执行此操作的最佳方法是使用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的双参数重载就足够简单了,如下所示(假设transformer是一个函数接口):

// 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中使用可变赋值通常是被禁止的,这是有充分理由的:变异会破坏并行化,java8中包含lambda的一个主要原因是允许更容易的并行编程。

一般来说,每当您希望以某种方式“总结”结果时,reduce(在其三个重载中的任何一个中)都是您的go-to方法。在使用时,学习如何有效地使用mapfilterreduceflatmap非常重要。

 类似资料:
  • 问题内容: 修改中的局部变量会产生编译错误: 正常 与Lambda 任何想法如何解决这个问题? 问题答案: 任何一种包装纸都是好的。 对于 Java 8+ ,请使用: …或数组: 使用 Java 10+ : 注意: 如果使用并行流, 请 非常小心。您可能无法获得预期的结果。诸如Stuart的其他解决方案可能更适合这些情况。 对于除 当然,这对于之外的其他类型仍然有效。您只需要将包装类型更改为或该类

  • 在中修改局部变量会导致编译错误: 典型的 和Lambda 你知道怎么解决这个问题吗?

  • 问题内容: 假设我有一个和一个。我想将每个转换器应用于列表中的每个字符串。 使用Java 8 lambda,我可以这样做: 但是我想做更多类似的事情,但是会导致编译时错误: 我刚刚开始玩lambda,所以也许我只是语法不正确。 问题答案: 使用流执行此操作的最佳方法是使用: 当然,这是假定非空的。如果有可能为空,则使用的两个参数重载来代替就足够简单了,就像这样(假定是一个功能接口): 出现编译器错

  • 问题内容: 我想使用匿名函数,所以我决定制作一个简单的主要查找器。这里是: 然而,我发现了什么,就是在每次访问,而我希望它是一个字面上的数字。我怎样才能使其成为替代? 问题答案: 您可以在创建lambda时“捕获” 这会将lambda的上下文设置为等于创建时的值。您还可以说,如果需要的话,它并不能完全捕获,但是可以满足您的需要。 这是一个查找问题,类似于具有定义函数的以下内容: