Функциональные интерфейсы как параметры метода - PullRequest
1 голос
/ 31 марта 2020

После написания моего собственного универсального функционального интерфейса и использования его с лямбдами, я должен использовать его в новом методе, который:

  • обрабатывает массив generic c в качестве входных данных, проверяя, что он имеет минимум 4 длины
  • обрабатывает любой экземпляр моего функционального интерфейса
  • обрабатывает любой экземпляр лямбда-выражения, который принимает аргумент и ничего не возвращает
  • , применяя к результату Ваш экземпляр функционального интерфейса (здесь я полагаю, что мне нужно использовать Consumer).

Никогда ранее не используя функциональные интерфейсы, кто-нибудь может объяснить мне, как я должен передавать 2 функциональных интерфейса в качестве параметров метода?

например, по телефону:

applyTransformations(new Integer[]{1,2,3,4}, add, printer);
@FunctionalInterface
public interface MyFunctionalInterface<T> {
    public T doOperation(T param1, T param2, T param3, T param4);
}
public class Lambdas {
    MyFunctionalInterface<Integer> add = (i1, i2, i3, i4) -> i1 + i2 + i3 + i4;
    MyFunctionalInterface<Integer> multiply = (i1, i2, i3, i4) -> i1 * i2 * i3 * i4;
    MyFunctionalInterface<String> concatenate = (s1, s2, s3, s4) -> s1 + s2 + s3 + s4;
    MyFunctionalInterface<String> concatenateWithSpacesBetween = (s1, s2, s3, s4) -> s1 + " " + s2 + " " + s3 + " " + s4;
}

Ответы [ 2 ]

3 голосов
/ 31 марта 2020

Может кто-нибудь объяснить, как я должен передавать 2 функциональных интерфейса в качестве параметров метода?

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

private static void printAddAndConcatenate(MyFunctionalInterface<Integer> add, MyFunctionalInterface<String> concatenate) {
    System.out.println(add.doOperation(1, 1, 1, 1));
    System.out.println(concatenate.doOperation("Hel", "lo ", "Wo", "rld"));
}

public static void main(String[] args) {
    printAddAndConcatenate(Lambdas.ADD, Lambdas.CONCATENATE);
}
2 голосов
/ 31 марта 2020

В простейшей форме вы можете представить преобразование функции прямо как:

static class Lambdas {
    static MyFunctionalInterface<Integer> add = (i1, i2, i3, i4) -> i1 + i2 + i3 + i4;
    static MyFunctionalInterface<Integer> multiply = (i1, i2, i3, i4) -> i1 * i2 * i3 * i4;
    static MyFunctionalInterface<String> concatenate = (s1, s2, s3, s4) -> s1 + s2 + s3 + s4;
    static MyFunctionalInterface<String> concatenateWithSpacesBetween = (s1, s2, s3, s4) -> s1 + " " + s2 + " " + s3 + " " + s4;

    public static void main(String[] args) {
        PrintStream printer = System.out;
        applyTransformations(new Integer[]{1, 2, 3, 4}, add, printer);
        applyTransformations(new Integer[]{2, 3, 4, 5}, multiply, printer);
        applyTransformations(new String[]{"one", "day", "or", "another"}, concatenate, printer);
        applyTransformations(new String[]{"yet", "another", "way", "forward"}, concatenateWithSpacesBetween, printer);
    }

    static <T> void applyTransformations(T[] input, MyFunctionalInterface<T> functionalInterface, PrintStream printer) {
        printer.println(functionalInterface.doOperation(input[0], input[1], input[2], input[3]));
    }
}

Но, как вы легко заметите, решение не может быть расширено, чтобы иметь более 4 элементов. Не стоит сильно беспокоиться, однако разработчики JDK уже позаботились о таком упрощении и предоставили способ непрерывной работы с потоком ввода, принимая два параметра за раз. Все это направляет вас к использованию Arrays.stream и далее Stream.reduce, который выполняет оценку по предоставленной BinaryOperator. Это сокращает ваш пример до

static class Lambdas {
    public static void main(String[] args) {
        PrintStream printer = System.out;
        applyTransformations(new Integer[]{1, 2, 3, 4}, Integer::sum, printer);
        applyTransformations(new Integer[]{2, 3, 4, 5}, (a, b) -> a * b, printer);
        applyTransformations(new String[]{"one", "day", "or", "another"}, String::concat, printer);
        applyTransformations(new String[]{"yet", "another", "way", "forward"}, (a, b) -> a + " " + b, printer);
    }

    static <T> void applyTransformations(T[] input, BinaryOperator<T> binaryOperator, PrintStream printer) {
        printer.println(Arrays.stream(input).reduce(binaryOperator));
    }
}

. В этой заметке вы должны быть осторожны с использованием оператора, так как он соответствует следующим атрибутам -

ассоциативный, не мешающая функция без сохранения состояния для объединения двух значений

...