Java的实用方法:如何合并两个Lambda表达式?

4
在.NET中,有一种简单的方法可以组合两个委托(.NET的lambda版本)。
基本上,你有:
LambdaType f1 = (a, b) => doSomething(a, b);
LambdaType f2 = (a, b) => doSomethingElse(a, b);
LambdaType combined = System.Delegate.Combine(f1, f2); 
// combined is equiv to: (a, b) => { f1.invoke(a, b); f2.invoke(a, b);};

Java中是否有类似的方法可以合并两个Lambda表达式?目前我还没有想到。尽管定义第二个Lambda表达式只是调用两个或多个Lambda表达式并不是太难,但这将是一个不错的小工具。


2
Combine 是什么作用?它是 AND 还是 OR - Konstantin Yovkov
1
@kocko 看起来是 andThen - Marko Topolnik
@MarkoTopolnik 是正确的。 - Joseph Nields
3个回答

12

您是在谈论Java 8的Lambda吗?因为这样的实用程序是存在的,例如:

Predicate<Foo> pred1 = f -> true; 
Predicate<Foo> pred2 = pred1.and(f -> false);
或者
Function<Int,Int> func1 = x -> x + 1;
Function<Int,Int> func2 = func1.andThen(x -> x*2);

你应该查看一下java.util.function包,因为你很可能会发现已经有这个功能了。

在你的具体示例中,你并没有组合两个函数,实际上,从函数的角度来看,你不能组合接受两个参数并返回一个参数(或void)的两个函数。

这是因为你缺少一个要求:第一个函数的码域必须对应于第二个函数的定义域,否则就无法进行组合。

你在这里真正做的是按顺序调用两个不相关的函数,使用完全相同的参数即可解决此问题:

BiConsumer<Foo,Bar> combination = (f,b) -> { doSomething(f,b); doSomethingElse(f,b); };

你能展示一下对于接受两个参数(并返回结果或者可能是void)的函数是如何工作的吗? - Marco13
@Marco13:你不能组合两个具有不同值域和定义域的函数。这根本没有意义,看看我的编辑,但你已经在你的答案中指出了它。 - Jack
你不一定要以严格的意义来编写它们。BiConsumer 不是一个函数,但定义了 andThen - Marko Topolnik

3

由于您的请求似乎涉及不返回任何内容的函数,因此适当的Java 8类型应该是BiConsumer。这使您可以按照自己的意愿进行操作:

BiConsumer<A,B> f1=(a,b) -> doSomething(a,b);
BiConsumer<A,B> f2=(a,b) -> doSomethingElse(a,b);
BiConsumer<A,B> combined = f1.andThen(f2);

这取决于函数类型提供组合函数的工厂方法,而不是允许任意组合。另一方面,这允许有意义的组合,例如对于Predicate,可以使用有用且易于理解的and/or,而不仅仅是调用两个函数的代码并返回任意结果。

0

函数组合(也适用于谓词)可能不是您想要的:它意味着将一个lambda应用于另一个的返回类型。这有几个影响。特别地,您不能以这种方式组合doSomething(a,b)doSomethingElse(a,b),因为没有任何一个函数的可能返回类型可以调用另一个函数。

由于Java中也没有LambdaType(不幸的是),您仍然必须选择特定的函数类型。通用写法,您将有两个如下的函数:

BiFunction<A,B,T> f0 = (a, b) -> doSomething(a, b); 
BiFunction<A,B,S> f1 = (a, b) -> doSomethingElse(a, b); 

TS分别是doSomethingdoSomethingElse的返回类型。为了将它们组合起来创建一个执行两者的函数,你可以简单地写成:

BiFunction<A,B,Void> f = (a,b) -> {
    doSomething(a,b); doSomethingElse(a,b); return null;
};

(或者您想要的任何返回类型...)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接