Sonar:用方法引用替换此 lambda。什么时候应该使用"stream()"?

Sonar : Replace this lambda with a method reference. When should "stream()" be used?

我想知道这三段代码有什么区别:

underlyingConnectors.values().stream().forEach(connector -> connector.start());

underlyingConnectors.values().forEach(connector -> connector.start());

underlyingConnectors.values().forEach(Connector::start);

第二行编译正常,但我的 Ecplipse IDE 抱怨“声纳:用方法引用替换此 lambda”。

如何选择合适的代码使用?每个都有特定的用例吗?

两行都是正确的。这只是声纳棉绒的警告。方法引用是 lambda 的一种简单形式,以防您只返回一个方法。

第一行包含对 stream() 的不必要调用,后两行是见仁见智的问题。如果你想写最短最简洁的代码,你会使用最后一个。它们都以相同的方式工作,主要是关于风格。

stream() 是不必要的,因为 values() returns 一个 Collection 扩展了 Iterable 已经有 forEach(Consumer<? super T> action)

如果您只是通过 .forEach() 对每个元素执行一次操作,则可以省略 .stream()。调用 .stream() 是多余的。

underlyingConnectors.values().stream().forEach(connector -> connector.start());
underlyingConnectors.values().forEach(connector -> connector.start());

第 2 行是正确的。

如果您只是对每个条目应用一个操作,那么只需使用方法引用,无需编写 lambda。这基本上是一个 shorthand.

underlyingConnectors.values().forEach(connector -> connector.start());
underlyingConnectors.values().forEach(Connector::start);

第 2 行是正确的。

第二个只是第一个的shorthand符号和第二个的第三个符号。一个经验法则是,如果一个方法没有像第二个那样的参数,你可以简单地用像第三个那样的符号替换它。

更一般地说,如果 lambda 表达式右侧 (RHS) 的表达式是 lambda 表达式左侧 (LHS) 的方法调用,不需要额外的参数或者是一个方法仅将表达式的左侧作为参数的调用,然后可以将 lambda 表达式替换为方法引用 - 一旦 RHS 采用两个参数,它就不像 Java 那样“漂亮”目前不支持将方法柯里化作为一种​​语言特性,但可以用包装器代替:

package com.example;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Application {

  private static final String LINEBREAK = System.lineSeparator();

  public static void main(String[] args) {
    final List<String> strings = Arrays.asList("Hello", "World", "!");

    strings.forEach(string -> System.out.print(string + LINEBREAK)); // 1

    strings.forEach(string -> Application.printWithLineBreakParameter(LINEBREAK).accept(string)); // 2

    strings.forEach(Application.printWithLineBreakParameter(LINEBREAK)); // 3
  }

  private static Consumer<String> printWithLineBreakParameter(final String lineBreak) {
    return (string) -> System.out.print(string + lineBreak);
  }
}

在这里,所有三个调用都是相等的,但 2 可以替换为 3,使其看起来比 1 更整洁。