Функция Pass с параметризованным поведением в Java

В Java я хочу определить нормализующую функцию, которая принимает одно число в качестве ввода, но поведение которого определяется несколькими параметрами.

По сути, эквивалент Java этого в Lisp:

(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, таких как Как передать функцию в качестве параметра в Java? Какая ближайшая замена указателя функции в Java? и Указатели функций в Java

Однако ни один из этих вопросов не касается передачи функции, поведение которой определяется параметрами, отличными от входного значения функции. Я не знаю заранее, каковы будут минимальные, максимальные, полные и потолочные параметры функции нормализации, но я хочу, чтобы только эффективная нормализующая функция принимала один аргумент, нормализуемое значение.

Ответ 1

Старомодный способ сделать это с помощью интерфейса:

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 вы можете избежать анонимного класса и просто использовать лямбда вместо этого:

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

Вы также можете сделать это inline:

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

Кроме того, вместо определения Normalizer вы можете просто использовать стандартный IntUnaryOperator функциональный интерфейс (и вызовите applyAsInt вместо of normalize).