【问题标题】:Replace this lambda with a method reference [duplicate]用方法引用替换这个 lambda [重复]
【发布时间】:2019-05-11 21:57:42
【问题描述】:

我有以下代码。 Sonar 抱怨用方法引用替换这个 lambda。

Stream.iterate(0, i -> i + 1).limit(100).map(i -> Integer.toString(i));

如果我用下面的代码替换它,它不会编译并出现编译错误:类型不匹配:无法从Stream<Object> 转换为<unknown>

Stream.iterate(0, i -> i + 1).limit(100).map(Integer::toString);

Integer::toString 如何将Stream<Object> 转换为<unknown>

【问题讨论】:

    标签: java java-8 sonarqube java-stream


    【解决方案1】:

    这是模棱两可的,因为staticnon-static toString() 方法都与功能签名Integer -> String 兼容。你可以改用String::valueOf

    【讨论】:

      【解决方案2】:

      您不能使用Integer::toString,因为Integer 有两个适合功能接口Function<Integer, String> 的实现,但您可以改用String::valueOf

      Stream.iterate(0, i -> i + 1)
              .limit(100)
              .map(String::valueOf)
              .collect(Collectors.toList())
      

      【讨论】:

      • 您不能输入Integer::toString,因为它接受int,而您的情况下您有Integer 使用。这是不正确的。 Lambda 可以隐式地装箱和拆箱。
      • @shmosel 那为什么IntStream.range(1, 100).mapToObj(Integer::toString).collect(Collectors.toList()) 有效?
      • 因为int 重载更适合原始流。
      • @shmosel 是的,你说得对Lambdas 可以隐式地装箱和拆箱
      【解决方案3】:

      正如@shmosel 所提到的,已经用方法引用替换了 lambda 会导致歧义,因为签名有两个 toString 方法:

      因为当您使用方法引用Integer::toString 调用map 时,对Stream.iterate(0, i -> i + 1) 的调用会返回Stream<Integer>,编译器不确定您是要执行Integer.toString(i) 还是i.toString(),因此会出现编译错误。

      所以这里是已经提供的其他选项:

      您可以使用IntStream.iterate 而不是Stream.iterate,然后调用mapToObj

      IntStream.iterate(0, i -> i + 1) // IntStream
               .limit(100) // IntStream
               .mapToObj(Integer::toString); // i1 -> Integer.toString(i1)
      

      intelliJ 建议的另一件事是您实际上可以这样做:

      Stream.iterate(0, i -> i + 1) // Stream<Integer>
            .limit(100) // Stream<Integer>
            .map(Object::toString); // integer -> integer.toString()
      

      其中Object::toString 等价于 lambda integer -&gt; integer.toString()


      另一方面,有趣的是,Sonar 建议将 lambda 替换为您显示的代码中的方法引用。 intelliJ IDEA 很聪明,没有提出建议。

      【讨论】:

        【解决方案4】:

        我认为IntStream 更适合您的代码:

        List<String> numbers = IntStream.range(0, 100)
                                        .mapToObj(String::valueOf)
                                        .collect(Collectors.toList());
        

        或者对于您的示例,请使用String.valueOf 转换int -&gt; String

        List<String> numbers = Stream.iterate(0, i -> i + 1)
                                     .limit(100)
                                     .map(String::valueOf)
                                     .collect(Collectors.toList());
        

        【讨论】:

          猜你喜欢
          • 2014-10-25
          • 2021-06-08
          • 1970-01-01
          • 1970-01-01
          • 2018-12-26
          • 2018-12-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多