Luc*_*uca 3 java generics lambda java-stream
我正在建立一种避免重复代码的框架,在某个时候,我需要将对象Foo的列表转换为对象Bar的列表。
我有扩展的数据库实体
public class BaseEntity {...}
Run Code Online (Sandbox Code Playgroud)
以及扩展的演示对象
public class BaseDTO<T extends BaseEntity> {...}
Run Code Online (Sandbox Code Playgroud)
所以
public class Foo extends BaseEntity {...}
Run Code Online (Sandbox Code Playgroud)
和
public class Bar extends BaseDTO<A extends BaseEntity> {
public Bar(Foo entity, Locale l) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
现在,使用流很容易将Foo列表转换为Bar列表
public abstract ClassThatUsesFooAndBar() {
public List<Bar> convertFooToBar(List<Foo> list) {
return list.stream().map(f -> new Bar(f, locale)).collect(...);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这里有个问题,这些Foo和Bar实际上是泛型(A和B),因此使用Foo和Bar的类实际上是ClassThatUsesAandB<A extends BaseEntity, B extends BaseDTO>,因此该函数也必须是抽象的,并以正确的A和B实现为样板代码实现,因为显然您无法实例化泛型类型。
有没有一种方法可以使用泛型/流/ lambdas创建可以编写一次的函数,从而使实现类无需重新实现它?函数签名为
public List<B> convertAToB(List<A> list);
Run Code Online (Sandbox Code Playgroud)
我希望我已经很清楚了,如果您需要进一步的解释,请询问
谢谢!
我认为最简单的方法是使用lambda进行转换。
public static <A,B> List<B> convertList(List<A> list, Function<A,B> itemConverter) {
return list.stream().map(f -> itemConverter.apply(f)).collect(...);
}
Run Code Online (Sandbox Code Playgroud)
然后您可以像这样使用它:
List<Bar> l = convertList(fooList,foo -> new Bar(foo.getBaz()));
Run Code Online (Sandbox Code Playgroud)
或者,如果需要,可以将其提取到其自己的命名类中:
public class Foo2BarConverter implements Function<Foo,Bar> {
@Override
public Bar apply(Foo f) {
return new Bar(f.getBaz());
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,鉴于我们可以对流进行处理,仅创建一个物化的Bar对象列表来创建新列表似乎有点浪费。转换后,我可能会直接链接要对列表执行的任何操作。