Java 中具有参数定义行为的传递函数

Sco*_*ons 2 java lambda function-pointers function parameter-passing

在 Java 中,我想定义一个规范化函数,该函数将一个数字作为输入,但其行为由多个参数定义。

本质上,在 Lisp 中的 Java 等价物是:

(define (normalizeVal min max floor ceiling)
  (lambda (x) (/ (* (- ceiling floor) (- x min)) (+ (- max min) floor))))
Run Code Online (Sandbox Code Playgroud)

在伪代码中,我想:

function parsing(data, normalizeValFunc) {
   for (datum in data):
      normalizeValFunc(datum);
}

var input = userData;
var min, max, floor, ceiling = /* Calculate min, max, floor, and ceiling */
var output = parsing(input, normalizeValFunc(min, max, floor, ceiling));
Run Code Online (Sandbox Code Playgroud)

在 Java 中将函数作为参数传递可能很棘手,因为函数在 Java 中不是一等对象。(也许 Java 8 Lambda 表达式会改变这一点?)其他问题解决了在 Java 中将函数作为参数传递的问题,例如如何在 Java 中将函数作为参数传递?Java 中最接近函数指针的替代品是什么?Java 中的函数指针

然而,这些问题都不涉及传递一个函数,该函数的行为由函数的输入值以外的参数定义。我事先不知道归一化函数的最小值、最大值、下限和天花板参数是什么,但我只希望有效归一化函数采用一个参数,即要归一化的值。

Ism*_*awi 5

这样做的老式方法是使用接口:

public interface Normalizer {
    int normalize(int value);
}
Run Code Online (Sandbox Code Playgroud)

然后,您将创建 a 的实例Normalizer,例如使用匿名类:

public static Normalizer normalizeValFunc(final int min, final int max, final int floor, final int ceiling) {
    return new Normalizer() {
        @Override public int normalize(int value) {
            /* Use min, max, floor, ceiling & value here to return something. */
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

然后你可以编写一个函数,它需要一个Normalizer

void parsing(int[] data, Normalizer normalizer) {
  // Call normalizer.normalize(...)
}
Run Code Online (Sandbox Code Playgroud)

并这样称呼它:

parsing(/* something here */, normalizeValFunc(min, max, floor, ceiling))
Run Code Online (Sandbox Code Playgroud)

在 Java 8 中,您可以避免使用匿名类而只使用 lambda:

public static normalizeValFunc(final int min, final int max, final int floor, final int ceiling) {
    return value -> /* Use min, max, floor, ceiling & value here to return something. */
}
Run Code Online (Sandbox Code Playgroud)

您也可以内联执行此操作:

parsing(/* something here */, value -> /* an expression using min, max, floor, ceiling, value */)
Run Code Online (Sandbox Code Playgroud)

此外,Normalizer您可以只使用标准IntUnaryOperator功能接口(并调用applyAsInt而不是normalize),而不是定义。