当前位置: 首页 > 知识库问答 >
问题:

Java lambda返回lambda

云浩然
2023-03-14

我正试图做一件在新JDK似乎是相对基本的事情

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

共有3个答案

单于亮
2023-03-14

我还没有深入研究类型推理如何与lambda一起工作的确切规则。不过,从一般的语言设计角度来看,并不总是可以编写语言规则来让编译器弄清楚我们认为它应该弄清楚的一切。我曾是Ada语言编译器的编译器维护者,我熟悉那里的许多语言设计问题。Ada在很多情况下使用类型推理(如果不查看包含构造的整个表达式,就无法确定构造的类型,我认为这个Javalambda表达式也是这种情况)。有一些语言规则会导致编译器拒绝某些表达式为模棱两可,而在理论上,实际上只有一种可能的解释。如果我没记错的话,一个原因是有人发现了这样一种情况,即让编译器找出正确解释的规则要求编译器使17通过表达式才能正确解释它。

因此,虽然我们可能认为编译器“应该”能够在特定情况下找出一些东西,但这显然是不可行的。

谭晓博
2023-03-14

我遇到了同样的问题,并且能够通过显式指定泛型类型参数来映射它,如下所示:

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

您遇到了Java的一个限制

在这里,< code>l.stream()。地图(n -

如果目标类型是已知的,很容易证明嵌套的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

 类似资料:
  • 问题内容: 例如我有一个功能: 我怎样才能返回AJAX后得到的? 问题答案: 因为请求是异步的,所以您无法返回ajax请求的结果(而同步ajax请求是一个 糟糕的 主意)。 最好的选择是将自己的回调传递给f1 然后,您将像这样致电:

  • 问题内容: 我在使用Ajax时遇到问题。 问题是,在获得ajax响应之前,它会返回cnt。因此它总是返回NULL。 有没有办法使正确的返回响应值? 谢谢! 问题答案: 由于AJAX请求是异步的,因此您的cnt变量将在请求返回并调用成功处理程序之前返回。 我建议重构您的代码以解决此问题。 一种方法是从AJAX请求的成功处理程序中调用调用了GetGrantAmazonItemCnt()的任何函数,此方

  • 我想在下面返回JSON。 {“名字”:“杰基”} 新来的春靴在这里。1天大。有没有合适的方法可以做到这一点?

  • 问题内容: 我创建了一个自定义错误类型来包装错误,以便更轻松地在Golang中进行调试。当有打印错误时它可以工作,但是现在引起了恐慌。 演示版 当我调用一个函数时,它不会返回错误,我仍然应该能够包装该错误。 预期的行为是,如果错误为nil,则应该简单地忽略它,不幸的是,它会做相反的事情。 我希望它能打印出来。而是即使错误为nil也会打印。 问题答案: 正在将err变量与nil进行比较,但实际上它是

  • 问题内容: 有人可以向我解释为什么返回类型 只是返回类型 我不明白为什么地图会映射到一个以上的值。TIA。 问题答案: 它返回具有 相同 名称的控件的所有参数值。 例如: 要么 任何选中/选择的值都将以以下形式出现: 对于表中的多个选择它也很有用: 与…结合

  • 问题内容: 我有一类这样的方法: 我如何在另一个类中调用此方法? 问题答案: 1. 如果要从中调用该方法的类位于同一包中,则创建该类的实例并调用该方法。 2. 使用 3. 最好有个赞等等。 例如:

  • 这三个函数的返回类型提示有什么不同吗? 他们都应该有< code>- 提问的动机是这个问题,这个很好的答案,以及我正在学习类型提示的事实。

  • 我使用类型TreeMap定义了一个集合 我想返回与包含给定字符串值的列表配对的字符串(TreeMap键)。例如,我有一个字符串“bob”存储在列表中的一对中,我想返回与“bob”所在的对列表相关联的Treemap的键(字符串)。我将如何执行此操作?