在Java中使用参数定义行为传递函数

时间:2014-06-10 18:17:59

标签: java function lambda parameter-passing function-pointers

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

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

(define (normalizeVal min max floor ceiling)
  (lambda (x) (/ (* (- ceiling floor) (- x min)) (+ (- max min) floor))))

在伪代码中,我想:

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));

在Java中将函数作为参数传递可能很棘手,因为函数不是Java中的第一类对象。 (也许Java 8 Lambda表达式改变了这个?)其他问题解决了在Java中将函数作为参数传递的问题,例如How to pass a function as a parameter in Java?What's the nearest substitute for a function pointer in Java?Function Pointers in Java

但是,这些问题都不涉及传递一个函数,该函数的行为由函数输入值以外的参数定义。我事先并不知道规范化函数的min,max,floor和ceiling参数是什么,但我只希望有效的规范化函数采用一个参数,即要规范化的值。

1 个答案:

答案 0 :(得分:4)

这种老式的做法是使用界面:

public interface Normalizer {
    int normalize(int value);
}

然后,您将创建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. */
        }
    };
}

然后你可以编写一个带Normalizer

的函数
void parsing(int[] data, Normalizer normalizer) {
  // Call normalizer.normalize(...)
}

并称之为:

parsing(/* something here */, normalizeValFunc(min, max, floor, ceiling))

在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. */
}

你也可以这样做内联:

parsing(/* something here */, value -> /* an expression using min, max, floor, ceiling, value */)

此外,您可以只使用标准的IntUnaryOperator功能界面(并调用Normalizer代替applyAsInt),而不是定义normalize