我正在构建一种避免代码重复的框架,在某个时候我需要将对象 Foo 列表转换为对象 Bar 列表。
我有扩展的数据库实体
public class BaseEntity {...}
以及扩展的展示对象
public class BaseDTO<T extends BaseEntity> {...}
所以
public class Foo extends BaseEntity {...}
和
public class Bar extends BaseDTO<A extends BaseEntity> {
public Bar(Foo entity, Locale l) {
...
}
}
现在使用流很容易将 Foo 列表转换为 Bar 列表
public abstract ClassThatUsesFooAndBar() {
public List<Bar> convertFooToBar(List<Foo> list) {
return list.stream().map(f -> new Bar(f, locale)).collect(...);
}
}
但是,问题来了,这些 Foo 和 Bar 实际上是泛型(A 和 B),所以使用 Foo 和 Bar 的类实际上是 ClassThatUsesAandB<A extends BaseEntity, B extends BaseDTO>
,因此该函数也必须是抽象的,并作为具有正确 A 和 B 实现的样板代码实现,因为显然您无法实例化泛型类型。
有没有办法使用generics/streams/lambdas来创建一个可以写一次的函数,这样实现类就不需要重新实现它了?函数签名为
public List<B> convertAToB(List<A> list);
我希望我已经足够清楚我需要什么,如果您需要进一步的解释,请询问
谢谢!
最佳答案
我认为最简单的方法是使用 lambda 进行转换。
public static <A,B> List<B> convertList(List<A> list, Function<A,B> itemConverter) {
return list.stream().map(f -> itemConverter.apply(f)).collect(...);
}
然后你可以像这样使用它:
List<Bar> l = convertList(fooList,foo -> new Bar(foo.getBaz()));
或者如果你愿意,你可以将它提取到它自己的命名类中:
public class Foo2BarConverter implements Function<Foo,Bar> {
@Override
public Bar apply(Foo f) {
return new Bar(f.getBaz());
}
}
顺便说一句,考虑到我们可以用流式处理做什么,创建一个新列表只是为了拥有 Bar
对象的物化列表似乎有点浪费。我可能会在转换后立即将我想对列表执行的任何操作链接起来。
关于Java 泛型和流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34228921/