【问题标题】:How to create composite lambda expression in java 8如何在 java 8 中创建复合 lambda 表达式
【发布时间】:2016-06-30 07:40:14
【问题描述】:

我正在尝试在 Java 8 中使用 lambda 表达式。 我要写的表达式的类型是:

BiConsumer<String, BiConsumer<Boolean,Integer>> cc2;

我应该可以写一个看起来有点像这样的表达式:

cc2 = (s,(b,i)) -> { System.out.println(s+b+i); }; // this does not compile

很遗憾,我找不到必须使用的确切语法。

【问题讨论】:

标签: java lambda java-8


【解决方案1】:

BiConsumer&lt;String, BiConsumer&lt;Boolean,Integer&gt;&gt; 类型声明了一个BiConsumer,也就是说,一个消费者消费了 2 个,而且只有 2 个参数。在这两个参数中,一个声明为String 类型,而另一个声明为BiConsumer&lt;Boolean,Integer&gt; 类型。

因此,这将编译:

BiConsumer<String, BiConsumer<Boolean,Integer>> cc2 = (s, c) -> {};

s 的类型为 Stringc 的类型为 BiConsumerc 的参数需要被捕获,而不是 lambda 参数。

这不是您想要的:您实际上想要使用 3 个参数,而不是 2 个。没有针对此要求的内置功能接口,但您可以自己制作:

@FunctionalInterface
interface TriConsumer<A,B,C> {
    void accept(A a, B b, C c);
}

然后,你可以使用它

TriConsumer<String,Boolean,Integer> tri = (s, b, i) -> System.out.println(s+b+i);

或者,您可以通过声明一个Function 来使用currying,该String 将返回双向消费者:

Function<String, BiConsumer<Boolean,Integer>> f = s -> (b, i) -> System.out.println(s+b+i);
f.apply("foo").accept(true, 1);

【讨论】:

  • 做这么简单的工作真的很奇怪,我需要声明任何东西,如果我需要声明接口,为什么要使用lambda,最好声明函数。我认为类似的东西(仍然干净)是可能的:(复制自 stackoverflow.com/questions/18400210/…Function&lt;Integer, Function&lt;Integer, UnaryOperator&lt;Integer&gt;&gt;&gt; tri = a -&gt; b -&gt; c -&gt; a + b + c; System.out.println(tri.apply(1).apply(2).apply(3)); 完全是功能,我认为是双消费者 - 但这是一种解决方法,但仍然很好,谢谢
  • @niedomnie 要使用 lambda,需要定义一个功能接口。 API中有一些内置但不可能所有组合(在Function3之后,为什么不是Function4和5...)
【解决方案2】:

Java 没有真正的函数类型(如真正的函数式语言)。相反,您需要定义一个功能接口。对于最多具有两个参数的函数和消费者,这些功能接口已在标准库中定义,但如果您需要三个参数,则必须自己定义。声明该接口是 Java 的实现方式。但是,看看您对 Tunaki 回答的评论,您不想这样做。

您可以使用在真正的函数式编程语言(但不是 Java)中非常常见的技巧。它被称为currying。具有两个参数的函数可以看作是读取第一个参数并返回读取第二个参数的函数的函数。第二个函数是第一个函数的输出。

然而,在您的示例代码中,第二个 BiConsumer 不是输出,而是输入!这意味着完全不同的东西。您定义了一个 BiConsumer,它接收回调作为输入。

相反,您需要定义一个提供 BiConsumer 作为输出的函数:

Function<String,BiConsumer<Boolean,Integer>> cc2;
cc2 = s -> (b,i) -> System.out.println(s + b + i); 

或提供消费者作为输出的两个函数:

Function<String, Function<Boolean, Consumer<Integer>>> cc2;
cc2 = s -> b -> i -> System.out.println(s + b + i);

但是,如果您问我,这与 Java 习惯用法相差太大。我会简单地定义那个接口。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    相关资源
    最近更新 更多