Functional programming Java8函数式编程-传递函数及其参数
我有一个关于Java8函数式编程的问题。我正在尝试使用函数式编程实现一些东西,需要一些关于如何实现的指导 我的要求是将每个方法执行封装在计时器函数中,计时器函数对方法执行进行计时。下面是计时器函数的示例,以及我需要计时的两个函数Functional programming Java8函数式编程-传递函数及其参数,functional-programming,java-8,Functional Programming,Java 8,我有一个关于Java8函数式编程的问题。我正在尝试使用函数式编程实现一些东西,需要一些关于如何实现的指导 我的要求是将每个方法执行封装在计时器函数中,计时器函数对方法执行进行计时。下面是计时器函数的示例,以及我需要计时的两个函数 timerMethod(String timerName, Function func){ timer.start(timerName) func.apply() timer.stop() } functionA(String arg1, String a
timerMethod(String timerName, Function func){
timer.start(timerName)
func.apply()
timer.stop()
}
functionA(String arg1, String arg2)
functionB(int arg1, intArg2, String ...arg3)
我试图将functionA
和functionB
传递给timerMethod
,但是functionA
和functionB
需要不同数量和类型的参数来执行
我有什么想法可以实现它吗
谢谢 不要保留论点,然后在最后一刻传递它们。立即传递它们,但通过使用另一个函数包装函数来延迟调用该函数:
Producer<?> f1 =
() -> functionA(arg1, arg2);
Producer<?> f2 =
() -> functionB(arg1, arg2, arg3);
SomeReturnType result = timedCurrifiedFunctionA.apply("a").apply("b");
这将对lambda中提供的参数形成一个闭包,这允许您稍后使用变量,即使通常情况下它们会因超出范围而被GC
注意,我有一个
?
作为生产者的类型,因为我不知道您的函数返回什么类型。将?
更改为每个函数的返回类型 为了使代码易于使用和维护,您应该将其分为两部分。一个是定时,另一个是调用,例如:
// v--- invoking occurs in request-time
R1 result1 = timerMethod("functionA", () -> functionA("foo", "bar"));
R2 result2 = timerMethod("functionB", () -> functionB(1, 2, "foo", "bar"));
// the timerMethod only calculate the timing-cost
<T> T timerMethod(String timerName, Supplier<T> func) {
timer.start(timerName);
try {
return func.get();
} finally {
timer.stop();
}
}
//v---调用在请求时发生
R1 result1=timerMethod(“functionA”,()->functionA(“foo”,“bar”);
R2结果2=时间方法(“函数B”,()->函数B(1,2,“foo”,“bar”);
//timerMethod只计算计时成本
T timerMethod(字符串timerName,供应商函数){
timer.start(timerName);
试一试{
返回函数get();
}最后{
timer.stop();
}
}
如果您想返回一个功能接口,而不是该方法的结果,您可以按如下操作:
Supplier<R1> timingFunctionA =timerMethod("A", ()-> functionA("foo", "bar"));
Supplier<R2> timingFunctionB =timerMethod("B", ()-> functionB(1, 2, "foo", "bar"));
<T> Supplier<T> timerMethod(String timerName, Supplier<T> func) {
// v--- calculate the timing-cost when the wrapper function is invoked
return () -> {
timer.start(timerName);
try {
return func.get();
} finally {
timer.stop();
}
};
}
Supplier timingFunctionA=timerMethod(“A”),()->functionA(“foo”,“bar”);
供应商计时功能B=计时方法(“B”),()->功能B(1,2,“foo”,“bar”);
供应商timerMethod(字符串timerName,供应商函数){
//v---计算调用包装器函数时的时间开销
返回()->{
timer.start(timerName);
试一试{
返回函数get();
}最后{
timer.stop();
}
};
}
笔记
如果所有函数的返回类型都是void
,您可以将供应商
替换为Runnable
,然后将timerMethod
的返回类型设置为void
&从timerMethod
中删除返回
关键字
如果您的某些函数将抛出选中的异常,您可以用可调用
替换供应商
&调用可调用#调用
导言
其他答案显示了如何使用闭包来捕获函数的参数,无论其数量如何。这是一种很好的方法,非常有用,如果您事先知道参数,那么就可以捕获它们
在这里,我想展示另外两种方法,它们不需要你事先知道论点
如果你从抽象的角度来考虑,就不存在有多个参数的函数。函数要么接收一组值(也称为元组),要么接收一个单参数并返回另一个接收另一个单参数的函数,该函数反过来返回另一个单参数函数,该函数返回。。。等,序列的最后一个函数返回实际结果(也称为currying)
但是,Java中的方法可能有多个参数。因此,挑战在于构建总是接收一个参数的函数(通过元组或curry),但实际上调用接收多个参数的方法
方法1:元组
因此,第一种方法是使用helper类,让函数接收一个元组,要么是Tuple2
,要么是Tuple3
:
因此,示例中的函数可能会收到一个Tuple2
作为参数:
Function<Tuple2<String, String>, SomeReturnType> functionA = tuple ->
functionA(tuple.getFirst(), tuple.getSecond());
现在,为了用timerMethod
方法装饰函数
,您需要做一些修改:
static <T, R> Function<T, R> timerMethod(
String timerName,
Function<? super T, ? extends R> func){
return t -> {
timer.start(timerName);
R result = func.apply(t);
timer.stop();
return result;
};
}
您可以像调用任何其他函数一样调用timedFunctionA
,在调用时立即将参数传递给它:
SomeReturnType resultA = timedFunctionA.apply(Tuple2.of("a", "b"));
您可以对示例中的函数b
采取类似的方法,只是需要对参数使用Tuple3
(注意varargs参数)
这种方法的缺点是需要创建许多Tuple
类,即Tuple2
、Tuple3
、Tuple4
,等等,因为Java缺乏对元组的内置支持
方法2:咖喱
另一种方法是使用一种称为的技术,即接受一个单参数的函数和返回另一个接受另一个单参数的函数等,序列的最后一个函数返回实际结果
下面是如何为双参数方法function
创建一个currified函数:
Function<Tuple2<String, String>, SomeReturnType> timedFunctionA = timerMethod(
"timerA",
tuple -> functionA(tuple.getFirst(), tuple.getSecond());
Function<String, Function<String, SomeReturnType>> currifiedFunctionA =
arg1 -> arg2 -> functionA(arg1, arg2);
如果要使用上面定义的timerMethod
方法装饰currifiedfunction
,可以执行以下操作:
SomeReturnType resultA = functionA.apply(Tuple2.of("a", "b"));
SomeReturnType result = currifiedFunctionA.apply("a").apply("b");
Function<String, Function<String, SomeReturnType>> timedCurrifiedFunctionA =
arg1 -> timerMethod("timerCurryA", arg2 -> functionA(arg1, arg2));
请注意,您只需要修饰序列的最后一个函数,即对方法进行实际调用的函数,这是我们想要度量的
对于示例中的方法functionB
,您可以采用类似的方法,不同的是,currified函数的类型现在是:
Function<Integer, Function<Integer, Function<String[], SomeResultType>>>
函数
至少可以说,这相当麻烦。因此,这就是Java中curried函数的缺点:表示其类型的语法。在…上
Function<Integer, Function<Integer, Function<String[], SomeResultType>>>