如何在Java 8中创建复合Lambda表达式

4
我正在尝试在Java 8中使用lambda表达式。 我想要编写的表达式类型是:
BiConsumer<String, BiConsumer<Boolean,Integer>> cc2;

我应该能够编写类似以下的表达式:

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

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


1
Java 8中的lambda带有两个箭头是什么意思? - Holger
2个回答

8
类型 BiConsumer<String, BiConsumer<Boolean,Integer>> 声明了一个 BiConsumer,即消费者只消费 2 个参数。这两个参数中,一个声明为类型 String,而另一个声明为类型 BiConsumer<Boolean,Integer>
因此,以下代码可以编译通过:
BiConsumer<String, BiConsumer<Boolean,Integer>> cc2 = (s, c) -> {};

s 的类型将会是 String,而 c 的类型将会是 BiConsumer。需要捕获 c 的参数,并且它们不会成为 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);

另外,您可以利用柯里化,通过声明一个接受String并返回双消费者的Function来实现:

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

做这么简单的工作,我需要声明任何东西,为什么我需要使用lambda如果我需要声明一个接口,最好声明函数。我认为类似的(仍然干净)是可能的:(从https://dev59.com/NWMl5IYBdhLWcg3wcmrD复制)Function<Integer,Function<Integer,UnaryOperator<Integer>>> tri = a-> b-> c-> a + b + c; System.out.println(tri.apply(1).apply(2).apply(3));确切的功能,biconsumer我想 - 但这是一个解决方法,但仍然很好,谢谢 - niedomnie
1
要使用lambda表达式,需要定义一个函数接口。API中有一些内置的函数接口,但不能涵盖所有组合(在Function3之后,为什么不是Function4和5...)。 - Tunaki

3

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

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

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

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

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

或者有两个函数提供Consumer作为输出:
Function<String, Function<Boolean, Consumer<Integer>>> cc2;
cc2 = s -> b -> i -> System.out.println(s + b + i);

但如果你问我,这太偏离Java语言的习惯用法了。我会简单地定义那个接口。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接