gpt4 book ai didi

Java lambda 返回一个 lambda

转载 作者:搜寻专家 更新时间:2023-10-30 23:03:00 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 才允许程序员省略这些不必要的类型参数重复(使用“菱形运算符”)。现在我们有类似的情况,将调用表达式包装到另一个方法中,将接收者变成参数,证明这种限制是不必要的。所以也许我们在 Java 10 中摆脱了这个限制……

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

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