我被告知将带有参数化构造函数的lambda转换为方法引用

时间:2017-05-18 00:45:38

标签: java lambda java-8 method-reference

假设我有一个类Gizmo,带有一个带String的构造函数。 假设我想将List<String>转换为List<Gizmo>

我可能会写:

List<String> strings = new ArrayList<>();
List<Gizmo> gizmos = strings
        .stream()
        .map(str -> new Gizmo(str))
        .collect(Collectors.toList());

现在,问题在于IntelliJ告诉我,我可以用方法引用替换lambda。事实上,我非常确定方法参考不能参数。

4 个答案:

答案 0 :(得分:9)

我认为InteliJ意味着取代

.map(str -> new Gizmo(str))

.map(Gizmo::new)

是构造函数引用。请参阅详细说明here

答案 1 :(得分:4)

  

现在,问题在于IntelliJ告诉我,我可以替换它   lambda与方法参考。

它只是意味着你可以改变这个:

.map(str -> new Gizmo(str))

到此:

.map(Gizmo::new)

您可以阅读有关Constructor method reference的更多信息。

答案 2 :(得分:1)

使用方法引用而不是lambda表达式时也会有一些优化。

Lambda表达式被去除静态/实例方法(取决于它是否真的是lambda/clojure),但方法引用不是。

在使用lambda表达式(t -> new Gizmo(t))的情况下,编译器将在您的类中生成一个额外的方法;看起来像这样:

  private static Gizmo lambda$main$0(String s) {
      return new Gizmo(s);   
  }

如果是方法引用(构造函数引用),它将不存在。

答案 3 :(得分:0)

方法引用就是:对方法的引用,无论方法实际具有多少个参数。对构造函数的引用只是引用构造函数的方法引用的特例。

假设您有一个Person类:

public class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age  age;
    }

    // getters, setters
}

现在还假设您有BiFunction<String, Integer, Person>将名称和年龄参数映射到Person类的实例:

BiFunction<String, Integer, Person> personCreator = 
    (String name, Integer age) -> new Person(name, age);

或者,由于编译器直接推断出lambda表达式的参数类型:

BiFunction<String, Integer, Person> personCreator = (name, age) -> new Person(name, age);

您可以按如下方式使用此2-arg功能:

Person joe = personCreator.apply("Joe", 25);

现在,您是否注意到(name, age) lambda表达式中参数的类型和顺序与构造函数中的参数类型和顺序相匹配?这意味着我们可能会使用方法引用:

BiFunction<String, Integer, Person> personCreator = Person::new;

它将按预期工作:

Person jane = personCreator.apply("Jane", 23);

这只是为了向您展示使用方法引用时参数的数量无关紧要。所有需要匹配的是功能接口的唯一一个抽象方法(在本例中为BiFunction.apply)的签名,其中包含构造函数的签名。

如果您想进一步阅读方法参考,请转到Java教程中的section about method references