如何在Java8中初始化通过:: new时将参数传递给类构造函数

col*_*sal 4 java-8 java-stream

我正在使用java 8流API对Store对象列表执行操作.

Store接受一个String论点和一个Mapper对象.Mapper对所有Store对象都是一样的.

问:我如何传递Mapper对象时我初始化Store这里.map(Store::new)

public class Store {
    public Store(String name, Mapper mapper) {
    }
}

public class Mapper {
}

public class Test {
    public static void main(String[] args) {
        List<String> names = new ArrayList<String>();

        Mapper mapper = new Mapper();
         // compile time problem at Store::new because it takes 2 arguments
         List<Store> actions = 
             names.stream()
              .map(Store::new)
              .collect(Collectors.toList());
    }
}
Run Code Online (Sandbox Code Playgroud)

Fed*_*ner 7

您不能将方法引用用于需要接收自由变量的构造函数,即来自上下文的变量.

请参阅Java教程的"方法引用"部分以查找有关方法引用的更多信息.

您可以使用lambda表达式:

Mapper mapper = new Mapper();

List<Store> actions = 
    names.stream()
        .map(name -> new Store(name, mapper))
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

无论出于何种原因,如果你坚持使用方法参考,你仍然可以,尽管解决方案更复杂和繁琐.实际上,从所有可能的观点来看,使用lambda表达式而不是我在下面介绍的hack会更好.我写它只是为了表明方法引用只有在你已经拥有一个签名与预期签名匹配的方法或构造函数时才有用.

假设您声明了这个辅助方法:

public static <T, U, R> Function<T, R> bindSecond(
        BiFunction<T, U, R> biFunction, 
        U free) {
    return t -> biFunction.apply(t, free);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我正在创建并返回一个1参数函数,该函数将其唯一的一个参数应用于给定的双函数(一个2参数函数),以及给定的自由变量.换句话说,我将给定的自由变量绑定到给定的双函数作为其第二个参数.

在你的例子中,Store::new实际上是一个带有两个参数(namemapper)并返回一个值(新Store实例)的双功能,并且你得到了那个编译错误,因为Stream.map需要一个1-参数函数,它将流的元素作为唯一的一个参数.

bindSecond辅助方法实际上变换给定的双功能和自由变量到所述的签名相匹配的1参数函数Stream.map方法.

您可以按如下方式使用它:

Mapper mapper = new Mapper();

List<Store> actions = 
    names.stream()
        .map(bindSecond(Store::new, mapper))
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但同样,我认为在一个简单的lambda表达式中使用它没有任何意义.


Eug*_*ene 6

使用 lambda 表达式而不是方法引用

  .map(name -> new Store(name, mapper))
Run Code Online (Sandbox Code Playgroud)