Java实用程序方法结合两个lambdas?

时间:2015-07-29 14:31:41

标签: java lambda java-8

在.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中是否有这样的结合两个lambdas?什么都没想到。它是一个很好的小实用程序,虽然说实话上并不太难以定义只调用两个(或更多)的第二个lambda。

3 个答案:

答案 0 :(得分:11)

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

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)的函数。

这是因为您缺少要求:第一个函数的codomain必须与第二个函数的domain对应,否则无法完成组合。

你在这里真正做的是顺序调用具有相同参数的两个不相关的函数。这个问题可以通过完全相同的事情来解决:

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

答案 1 :(得分: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);

这依赖于为组合函数提供工厂方法的函数类型,而不是允许任意组合,另一方面,这允许具有有意义的组合,例如and / or for {{ 1}}做一些有用且可理解的事情,而不仅仅是调用两个函数的代码并返回任意结果。

答案 2 :(得分: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;
};

(或者你想要的任何回报类型......)