简体   繁体   English

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

[英]I'm told to convert a lambda with a parameterized constructor to a method reference

Lets say I have a class Gizmo with a constructor that takes a String. 假设我有一个带有构造函数的类Gizmo ,它带有一个String。 Lets say I want to convert a List<String> to a List<Gizmo> . 假设我想将List<String>转换为List<Gizmo>

I might write: 我可能会写:

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

Now, the problem is that I'm told by IntelliJ that I can replace the lambda with a method reference. 现在,问题是IntelliJ告诉我我可以用方法引用替换lambda。 Thing is, I'm pretty sure method references can't take parameters. 事实是,我很确定方法引用不能参数。

I think InteliJ means replacing 我认为InteliJ意味着取代

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

with

.map(Gizmo::new)

which is a constructor reference. 这是一个构造函数引用。 See detailed explanation here . 请参阅此处的详细说明

Now, the problem is that I'm told by IntelliJ that I can replace the lambda with a method reference. 现在,问题是IntelliJ告诉我我可以用方法引用替换lambda。

it simply means you can change this: 它只是意味着你可以改变这个:

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

to this: 对此:

.map(Gizmo::new)

you can read more about Constructor method reference . 您可以阅读有关构造方法参考的更多信息。

There is also a slight optimization when using a method reference instead of a lambda expression also. 使用方法引用而不是lambda表达式时也会略有优化。

Lambda expressions are de-sugared to static/instance method (depends if it's really a lambda/clojure ), but method references are not. Lambda表达式是对静态/实例方法的去糖(取决于它是否真的是lambda/clojure ),但方法引用不是。

In your case when using a lambda expression ( t -> new Gizmo(t) ) compiler will generate an extra method in your class; 在你使用lambda表达式的情况下( t -> new Gizmo(t) )编译器会在你的类中生成一个额外的方法; that would look like this: 看起来像这样:

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

In case of a method reference (constructor reference) it will not be present. 在方法引用(构造函数引用)的情况下,它将不存在。

A method reference is just that: a reference to a method, no matter how many arguments the method actually has. 方法引用就是:对方法的引用,无论方法实际具有多少个参数。 A reference to a constructor is just a special case of method reference that references a constructor. 对构造函数的引用只是引用构造函数的方法引用的特例。

Suppose you have a Person class: 假设你有一个Person类:

public class Person {

    private String name;
    private int age;

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

    // getters, setters
}

Now also suppose you have a BiFunction<String, Integer, Person> that maps name and age arguments to instances of the Person class: 现在还假设您有一个BiFunction<String, Integer, Person> ,它将名称和年龄参数映射到Person类的实例:

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

Or, as the types of the parameter of a lambda expression are directly inferred by the compiler: 或者,由于编译器直接推断出lambda表达式的参数类型:

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

You can use this 2-arg function as follows: 您可以使用以下2-arg函数:

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

Now, did you notice that the type and order of the parameters in the (name, age) lambda expression match those in the constructor? 现在,您是否注意到(name, age) lambda表达式中参数的类型和顺序与构造函数中的参数类型和顺序相匹配? This means we might use a method reference instead: 这意味着我们可能会使用方法引用:

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

And it will work, as expected: 它将按预期工作:

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

This is just to show you that the number of arguments doesn't matter when using method references. 这只是为了向您展示使用方法引用时参数的数量无关紧要。 All that needs to match is the signature of the only one abstract method of a functional interface (in this case BiFunction.apply ) with the signature of the constructor. 所有需要匹配的是具有构造函数签名的功能接口(在本例中为BiFunction.apply )中唯一一个抽象方法的签名。

If you want to further read about method references, go to the section about method references in the Java Tutorial. 如果要进一步阅读有关方法引用的信息,请转到Java教程中有关方法引用部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM