String to Method in Java 8 的映射,传递参数
Map of String to Method in Java 8, passing parameters
好吧,我一直在努力寻找这个问题的答案,但我无法理解新的 java 8 lambda 和方法引用。
我正在编写 SVM 解码器。我有一个由 libSVM 创建的模型,可以获取所有相关信息,如内核类型和常量,如 rho 和 gamma。我有一个函数,它接受一个向量并使用模型的内核类型对其进行分类。目前我只是用一个开关来确定要使用哪个内核:
public double classify(FeatureVector v){
double fx = 0.0;
switch(kernel){
case "linear":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * crossProduct(xi, v));
}
break;
case "polynomial":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * polynomialKernel(xi, v));
}
break;
case "rbf":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * rbfKernel(xi, v));
}
break;
case "sigmoid":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * sigmoidKernel(xi, v));
}
break;
default:
break;
}
return fx - rho;
}
现在,这工作正常。但它很丑陋且难以遵循。我一直在阅读 8 中的 lambda 和方法参考,但我就是想不通。不管怎样,我的最终想法是将字符串(内核名称)映射到每个内核的方法。然后将整个分类方法简化为:
public double classify(FeatureVector v){
double fx = 0.0;
//get the method from map, this is where I need the help
for(FeatureVector xi : supportVectors){
//and how do I then pass params to the method?
fx += (xi.getWeight() * kernelMethod(xi, v));
}
return fx - rho;
}
可能还有一种方法可以使用流来执行整个 for-each 循环,但首先我想了解 lambda 和方法引用。
定义地图 Map<String, BiFunction<FeatureVector, FeatureVector, Double>> functions
,添加您的功能,例如functions.put("linear", ThisClass::crossProduct)
然后做
BiFunction<FeatureVector, FeatureVector, Double> function = functions.get(...);
fx += xi.getWeight() * function.apply(xi, v);
如果 crossProduct 和 co。不是静态的,您需要改为 this::crossProduct
。
不要使用 lambda
只是为了使用 lambda
...
我会像这样简单地重构您的代码:
for(FeatureVector xi : supportVectors)
{
switch(kernel){
case "linear":
fx += (xi.getWeight() * crossProduct(xi, v));
break;
case "polynomial":
fx += (xi.getWeight() * polynomialKernel(xi, v));
break;
case "rbf":
fx += (xi.getWeight() * rbfKernel(xi, v));
break;
case "sigmoid":
fx += (xi.getWeight() * sigmoidKernel(xi, v));
break;
}
}
随着时间的推移,您可能想阅读有关 polymorphism to avoid this kind of switch statement which is most likely to become spaghetti code 的内容。
好吧,我一直在努力寻找这个问题的答案,但我无法理解新的 java 8 lambda 和方法引用。
我正在编写 SVM 解码器。我有一个由 libSVM 创建的模型,可以获取所有相关信息,如内核类型和常量,如 rho 和 gamma。我有一个函数,它接受一个向量并使用模型的内核类型对其进行分类。目前我只是用一个开关来确定要使用哪个内核:
public double classify(FeatureVector v){
double fx = 0.0;
switch(kernel){
case "linear":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * crossProduct(xi, v));
}
break;
case "polynomial":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * polynomialKernel(xi, v));
}
break;
case "rbf":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * rbfKernel(xi, v));
}
break;
case "sigmoid":
for(FeatureVector xi : supportVectors){
fx += (xi.getWeight() * sigmoidKernel(xi, v));
}
break;
default:
break;
}
return fx - rho;
}
现在,这工作正常。但它很丑陋且难以遵循。我一直在阅读 8 中的 lambda 和方法参考,但我就是想不通。不管怎样,我的最终想法是将字符串(内核名称)映射到每个内核的方法。然后将整个分类方法简化为:
public double classify(FeatureVector v){
double fx = 0.0;
//get the method from map, this is where I need the help
for(FeatureVector xi : supportVectors){
//and how do I then pass params to the method?
fx += (xi.getWeight() * kernelMethod(xi, v));
}
return fx - rho;
}
可能还有一种方法可以使用流来执行整个 for-each 循环,但首先我想了解 lambda 和方法引用。
定义地图 Map<String, BiFunction<FeatureVector, FeatureVector, Double>> functions
,添加您的功能,例如functions.put("linear", ThisClass::crossProduct)
然后做
BiFunction<FeatureVector, FeatureVector, Double> function = functions.get(...);
fx += xi.getWeight() * function.apply(xi, v);
如果 crossProduct 和 co。不是静态的,您需要改为 this::crossProduct
。
不要使用 lambda
只是为了使用 lambda
...
我会像这样简单地重构您的代码:
for(FeatureVector xi : supportVectors)
{
switch(kernel){
case "linear":
fx += (xi.getWeight() * crossProduct(xi, v));
break;
case "polynomial":
fx += (xi.getWeight() * polynomialKernel(xi, v));
break;
case "rbf":
fx += (xi.getWeight() * rbfKernel(xi, v));
break;
case "sigmoid":
fx += (xi.getWeight() * sigmoidKernel(xi, v));
break;
}
}
随着时间的推移,您可能想阅读有关 polymorphism to avoid this kind of switch statement which is most likely to become spaghetti code 的内容。