简体   繁体   English

多个lambda方法引用

[英]Multiple lambda method references

It's possible to chain/concatenate what is done with elements in a lambda expression like this: 可以链接/连接lambda表达式中的元素所执行的操作,如下所示:

list.forEach(s -> {
        System.out.println(s.toLowerCase());
        System.out.println(s.toUpperCase());
});

Is there a way to do this also with method references? 有没有办法用方法引用来做到这一点? Something like this: 像这样的东西:

list.forEach({
    System.out::println(String::toLowerCase);
    System.out::println(String::toCase);
});

I know I could do this in four separate calls (which do also more, that is mutate the values): 我知道我可以在四个单独的调用中执行此操作(这也会更多,这会改变值):

list.replaceAll(String::toLowerCase);
list.forEach(System.out::println);
list.replaceAll(String::toUpperCase);
list.forEach(System.out::println);

I can't even do something easy like this: 我甚至不能像这样轻松做事:

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

chaining is possible through default methods of the functional interfaces. 通过功能接口的默认方法可以链接。 But the "problem" is that there that the inference engine does not have enough information to determine that the left hand side is the same functional interface when you're returning the right hand side of the compositing expression. 但是“问题”在于,当您返回合成表达式的右侧时,推理引擎没有足够的信息来确定左侧是相同的功能接口。

To provide that information you either have to cast the statement: 要提供该信息,您必须转换声明:

  List<String> l = Collections.emptyList();
  l.forEach(((Consumer<String>)System.out::println).andThen(System.out::println));

Or assign it to a variable first: 或者首先将其分配给变量:

  Consumer<String> cons = System.out::println;
  Collections.<String>emptyList().forEach(cons.andThen(System.out::println));

Alternatively you could also write static helper methods that do what you want 或者,您也可以编写可以执行所需操作的静态帮助程序方法

Collections.<String>emptyList().forEach(combine(System.out::println, System.out::println));

static <T> Consumer<T> combine(Consumer<T>... consumers) {
    // exercise left to the reader
}

No you can't use method references as you have suggested. 不,你不能像你建议的那样使用方法引用。 Method references are really just a syntactic replacement for a lambda expression. 方法引用实际上只是lambda表达式的语法替代。 So that instead of: 所以,而不是:

text -> console.print(text)

You can avoid introducing an unnecessary variable and instead use 您可以避免引入不必要的变量而是使用

console::print

So when you mention that you can't do something such as: 所以当你提到你不能做的事情,比如:

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

This is just a syntactic shortcut for 这只是一个语法快捷方式

list.forEach({
    c -> System.out.println(c);
    c -> System.out.println(c);
});

This really makes no sense. 这没有任何意义。 There's no variable representing the item in the list (which would have to be outside the block) and the two 'statements' are lambda expressions with nothing to be applied to. 没有表示列表中项目的变量(必须在块之外),并且两个'语句'是lambda表达式,没有任何内容可以应用。

Method references are a pretty neat shortcut to avoid having an unnecessary variable but they are just a substitute for a more verbose lambda expression and can't be used as an independent statement in a block. 方法引用是一个非常简洁的快捷方式,可以避免使用不必要的变量,但它们只是一个更详细的lambda表达式的替代,不能用作块中的独立语句。

There is no point in converting 转换没有意义

list.forEach(s -> {
    System.out.println(s.toLowerCase());
    System.out.println(s.toUpperCase());
});

to

list.forEach({
    System.out::println(String::toLowerCase);
    System.out::println(String::toUpperCase);
});

as there is no win in clarity, the latter even consists of more characters than the former, if we use the same indention and insert the Upper you have left off the second variant. 因为在清晰度上没有胜利,后者甚至包含比前者更多的字符,如果我们使用相同的缩进并插入Upper那么你已经离开了第二个变体。 So why should we have such an alternative form? 那么我们为什么要有这样一种替代形式呢?

Method reference have been invented as a feature allowing a dense syntax for a single method delegation, were declaring and referencing the parameters could really make a difference. 方法参考已被发明为允许单个方法委派的密集语法的特征,声明和引用参数确实可以产生影响。 Even replacing a sole s->System.out.println(s) with System.out::println is no that big win, but at least, there is some. 即使用System.out::println替换唯一的s->System.out.println(s)也没有那么大的胜利,但至少有一些。 Further, encoding the method reference at bytecode level can be more compact because the target method can be directly referenced just like the synthetic method holding a lambda expression's code. 此外,在字节码级别对方法引用进行编码可以更紧凑,因为目标方法可以直接引用,就像保存lambda表达式代码的合成方法一样。 For compound method references, there is no such compact form. 对于复合方法参考,没有这种紧凑的形式。


Since your desired operation consist of operations of different kinds, you may use the Stream API, which is intended to combine such operations: 由于您所需的操作包含不同类型的操作,因此您可以使用Stream API,它旨在组合这些操作:

list.stream().flatMap(s->Stream.of(s.toLowerCase(), s.toUpperCase()))
    .forEach(System.out::println);

and if you want to include method references for everything, at all costs, you may do it the following way: 如果您想不惜一切代价包含所有内容的方法引用,您可以通过以下方式进行:

list.stream()
    .flatMap(s->Stream.<UnaryOperator<String>>of(String::toLowerCase, String::toUpperCase)
        .map(f->f.apply(s)))
    .forEach(System.out::println);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 用流/ lambda /方法引用替换常规的foreach - Replace the regular foreach with stream/lambda/method references Java Lambda 表达式和方法对通用方法的引用 - Java Lambda Expressions and Method References to Generic Methods 如何将Lambda表达式写入方法引用? - How to write Lambda expression into method references? 实用程序类,用于引导lambda表达式或方法引用以进行方法链接? - Utility Class to bootstrap lambda expressions or method references for method chaining? 如何将具有动态值的lambda过滤器转换为方法引用 - How to convert lambda filters with dynamic values to method references 有没有更简单的方法来处理OSGi中的MULTIPLE引用? - Is there a simpler method for handling MULTIPLE references in OSGi? 当方法引用用作 KeyBy 的输入参数时,lambda 和双冒号有何不同? - How do lambda and double colons differ when method references are used as input parameters to KeyBy? 当有多个 arguments 时,方法引用如何在后台工作 - How does method references work under hood when there are multiple arguments 将同一对象的多个引用传递给一个方法是一种好习惯吗? - Is it good practice to pass multiple references to the same object into a method? 具有多个匹配目标类型的 lambda 表达式的方法签名选择 - Method signature selection for lambda expression with multiple matching target types
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM