Функциональные интерфейсы как параметры метода

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

  • обрабатывает общий массив в качестве входных данных, проверяя, что он имеет длину не менее 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;
}

person Alexandra Dediu    schedule 31.03.2020    source источник
comment
Можете ли вы показать некоторые примеры входных и выходных данных? Что вы хотите, чтобы ваша программа делала, когда получала какой ввод?   -  person Sweeper    schedule 31.03.2020
comment
По сути, метод applyTransformations() принимает в качестве параметров общий массив (он может быть типа String, Integer и т. д.), принимает любой возможный экземпляр моего объявленного функционального интерфейса — добавляет, умножает для целых чисел и объединяет для строк, и, наконец, параметр принтера должен печатать в консоли результат данной лямбды. Короче говоря, applyTransformations(new Integer[]{1,2,3,4}, add, принтер) должно отображать в консоли только 10.   -  person Alexandra Dediu    schedule 31.03.2020


Ответы (2)


может кто-нибудь объяснить мне, как я должен передать 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);
}
person PiggyPiglet    schedule 31.03.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));
    }
}

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

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

person Naman    schedule 31.03.2020
comment
Большое спасибо за объяснения и очень конкретные фрагменты кода! Я был близок к вашему решению, но пытался использовать Comparator вместо Printstream и немного застрял в части дженериков... - person Alexandra Dediu; 31.03.2020