【问题标题】:Functional interfaces as method parameters功能接口作为方法参数
【发布时间】:2020-07-12 04:31:13
【问题描述】:

在编写了我自己的通用函数接口并将其与 lambdas 一起使用后,我必须在一个新方法中使用它:

  • 处理一个泛型数组作为输入,检查它的长度是否至少为 4
  • 处理我的功能接口的任何实例
  • 处理任何 lambda 表达式的实例,它接受一个参数并且不返回任何内容
  • 应用到功能接口实例的结果(这里我想我必须使用消费者)。

以前从未使用过函数式接口,谁能解释一下我应该如何将 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;
}

【问题讨论】:

  • 你能展示一些示例输入和输出吗?当收到什么输入时,你希望你的程序做什么?
  • 基本上,applyTransformations() 方法将一个泛型数组(它可以是字符串、整数等类型)作为参数,接受我声明的功能接口的任何可能实例 - 添加、乘以整数并连接字符串和最后的打印机参数应该在控制台中打印给定 lambda 的结果。所以简而言之,applyTransformations(new Integer[]{1,2,3,4}, add, printer) 在控制台中应该只显示 10。

标签: java lambda functional-interface


【解决方案1】:

在最简单的形式中,您可以将函数转换直接表示为:

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

在此注意,您必须小心使用运算符,例如它遵守以下属性--

一个关联的、无干扰的、无状态的函数,用于组合两个 价值观

【讨论】:

  • 非常感谢您的解释和非常具体的代码sn-ps!我接近你的解决方案,但我试图使用 Comparator 而不是 Printstream 并且在泛型部分卡住了一点......
【解决方案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);
}

【讨论】:

    猜你喜欢
    • 2019-07-29
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2020-08-10
    • 2017-03-05
    相关资源
    最近更新 更多