Java8-在stream.map()中链接构造函数调用和setter

Java8-在stream.map()中链接构造函数调用和setter,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我有一节课 class Foo{ String name; // setter, getter } 它只有一个默认构造函数 然后,我尝试从某个字符串创建一个Foo列表: Arrays.stream(fooString.split(",")) .map(name -> { Foo x = new Foo(); x.setName(name); return

我有一节课

class Foo{
    String name;
    // setter, getter
}
它只有一个默认构造函数

然后,我尝试从某个字符串创建一个
Foo
列表:

Arrays.stream(fooString.split(","))
            .map(name -> {
                Foo x = new Foo();
                x.setName(name);
                return x;

            }).collect(Collectors.toList()));

由于没有采用名称的构造函数,我不能简单地使用方法引用。当然,我可以通过构造函数调用和setter将这三行代码提取到一个方法中,但是有没有更好或更简洁的方法呢?(无需更改生成的文件
Foo

在这种情况下,除非您添加一个以名称为参数的构造函数,或者创建一个创建实例的构造函数,否则您没有太多的替代方法。

不,没有更好的方法

正如您在问题中所说,唯一的选择是为
Foo
对象创建工厂:

public class FooFactory {
    public static Foo fromName(String name) {
        Foo foo = new Foo();
        foo.setName(name);
        return foo;
    }
}
然后像这样使用它:

Arrays.stream(fooString.split(",")).map(FooFactory::fromName).collect(toList());

如果要拆分的名称很多,可以使用
Pattern.compile(“,”).splitAsStream(fooString)
(并将已编译的模式存储在常量中以避免重复),而不是
Arrays.stream(fooString.split(“,”)
,如果这种情况反复发生,您可以创建一个通用实用程序方法来处理给定一个属性值构造对象的问题:

public static <T,V> Function<V,T> create(
    Supplier<? extends T> constructor, BiConsumer<? super T, ? super V> setter) {
    return v -> {
        T t=constructor.get();
        setter.accept(t, v);
        return t;
    };
}


顺便说一下,如果
fooString
变得非常大,并且/或者可能包含很多元素(在拆分之后),那么使用
Pattern.compile(“,”).splitAsStream(fooString)
而不是
Arrays.stream(fooString.split(“,”)可能更有效

另一个没有人提到的替代方案是子类
Foo
类,但是这可能有一些缺点-很难说它是否适合解决您的问题,因为我不知道上下文

public class Bar extends Foo {

    public Bar(String name) {
        super.setName(name);
    }

}
.map(n->newfoo(){{{name=n;}}})

这将使用初始化块来设置实例变量


但是有一个警告:返回的对象实际上不是
Foo
类型,而是扩展
Foo
的新的匿名类。当你遵循Liskov替换原则时,这应该不是一个问题,但是有一些情况可能会引起关注。

如果流中有zip……或者:.map(n->new Foo(){{{setName(n);}}})亲爱的holger你能给我提供一个链接到一个好的教程来学习使用这个技能吗,这是一个模式吗,这样做有名字吗??
List<List<String>> l = Arrays.stream(fooString.split(","))
    .map(create(ArrayList<String>::new, List::add)).collect(Collectors.toList());
public class Bar extends Foo {

    public Bar(String name) {
        super.setName(name);
    }

}