在.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。
答案 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);
其中T
和S
分别是doSomething
和doSomethingElse
的返回类型。为了组合这些并创建一个执行两者的功能,您只需编写
BiFunction<A,B,Void> f = (a,b) -> {
doSomething(a,b); doSomethingElse(a,b); return null;
};
(或者你想要的任何回报类型......)