gpt4 book ai didi

Java lambda 返回一个 lambda

转载 作者:IT老高 更新时间:2023-10-28 20:46:13 24 4
gpt4 key购买 nike

我正在尝试在新的 JDK 8 函数式编程领域中做一些看似相对基本的事情,但我无法让它发挥作用。我有这个工作代码:

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

public class so1 {
public static void main() {
List<Number> l = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Callable<Object>> checks = l.stream().
map(n -> (Callable<Object>) () -> {
System.out.println(n);
return null;
}).
collect(Collectors.toList());
}
}

它需要一个数字列表并生成一个可以打印出来的函数列表。但是,显式转换为 Callable 似乎是多余的。在我和 IntelliJ 看来.我们都同意这也应该有效:

List<Callable<Object>> checks = l.stream().
map(n -> () -> {
System.out.println(n);
return null;
}).
collect(Collectors.toList());

但是我得到一个错误:

so1.java:10: error: incompatible types: cannot infer type-variable(s) R
List<Callable<Object>> checks = l.stream().map(n -> () -> {System.out.println(n); return null;}).collect(Collectors.toList());
^
(argument mismatch; bad return type in lambda expression
Object is not a functional interface)
where R,T are type-variables:
R extends Object declared in method <R>map(Function<? super T,? extends R>)
T extends Object declared in interface Stream
1 error

最佳答案

您遇到了 Java 8 目标类型的限制,该限制适用于方法调用的接收者。虽然目标类型(大多数情况下)适用于参数类型,但它不适用于调用方法的对象或表达式。

这里,l.stream().
map(n -> () -> {
System.out.println(n);
return null;
})
collect(Collectors.toList()) 的接收者方法调用,所以目标类型List<Callable<Object>>不考虑。

如果目标类型已知,则很容易证明嵌套的 lambda 表达式有效,例如

static <T> Function<T,Callable<Object>> toCallable() {
return n -> () -> {
System.out.println(n);
return null;
};
}

工作没有问题,你可以用它来解决你原来的问题

List<Callable<Object>> checks = l.stream()
.map(toCallable()).collect(Collectors.toList());

你也可以通过引入一个辅助方法来解决这个问题,它将第一个表达式的角色从方法接收器更改为参数

// turns the Stream s from receiver to a parameter
static <T, R, A> R collect(Stream<T> s, Collector<? super T, A, R> collector) {
return s.collect(collector);
}

并将原来的表达式改写为

List<Callable<Object>> checks = collect(l.stream().map(
n -> () -> {
System.out.println(n);
return null;
}), Collectors.toList());

这不会降低代码的复杂性,但可以毫无问题地编译。对我来说,这是一种似曾相识的感觉。当 Java 5 和泛型问世时,程序员不得不在 new 上重复类型参数。表达式,而简单地将表达式包装到泛型方法中证明推断类型没有问题。直到 Java 7 才允许程序员省略这些不必要的类型参数重复(使用“菱形运算符”)。现在我们也有类似的情况,把一个调用表达式包装成另一个方法,把receiver变成一个参数,证明这个限制是不必要的。所以也许我们可以摆脱 Java 10 中的这个限制……

关于Java lambda 返回一个 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26872827/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com