Передать функцию с определенным параметром поведением в Java

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

По сути, 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 лямбда-выражений меняет это?) Другие вопросы касаются проблемы передачи функций в качестве параметров в Java, например, Как передать функцию в качестве параметра в Java? Что является ближайшей заменой указателю на функцию в Java? и указатели на функции в Java

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

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

Вы можете также сделать это встроенным:

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

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

Другие вопросы по тегам