我正在寻找一种有效的设计模式,将一个对象列表映射到另一个对象列表,它们之间具有零或一对一的关系。我意识到这种事情通常是在关系数据库中完成的,但在这种特殊情况下,它确实需要在Java应用程序中完成......
假设第一个列表包含Foo
个对象(即List<Foo>
):
public class Foo {
public Integer id;
public String barName;
}
第二个列表包含Bar
个对象(即List<Bar>
):
public class Bar {
public Integer fooId;
public String name;
}
如何最有效地将所有name
属性从Bar
映射到Foo
等于Bar.fooId
的{{1}}对象?
我能想到的最好的是:
Foo.id
编辑:基于多个答案,我改进了我的代码如下:
void mapFooBar(List<Foo> fooList, List<Bar> barList) {
for (Bar bar : barList) {
for (Foo foo : fooList) {
if (bar.fooId.equals(foo.id)) foo.barName = bar.name;
}
}
}
有更好的方法吗?
答案 0 :(得分:1)
这具有N * M
的复杂性,这意味着如果你有5个foo和8个bar,则必须执行循环40次
class Container{
List<Foo> foos;
List<Bar> bars;
}
如果您使用Map<Integer, Container>
,则N + M
(5 + 8 = 13次)
迭代两个列表并将其映射到id
另见
答案 1 :(得分:1)
嗯。假设“主键”是唯一的,我可能会将Bar列表转换为以fooId作为键并且整个对象或名称作为值的映射。然后我将遍历Foo列表并查看id属性是否存在于地图中。如果是这样,我会将bar.name映射到foo.barName;
答案 2 :(得分:1)
我认为您正在寻找的是类似Apache BeanUtils或Springs的实现。只需确保要在两个对象之间复制数据的属性名称相同。所以拿你的代码:
void mapFooBar(List<Foo> fooList, List<Bar> barList) {
for (Bar bar : barList) {
for (Foo foo : fooList) {
if (bar.fooId.equals(foo.id)) {
BeanUtils.copyProperties(foo, bar);
}
}
}
}
现在复制已完成,让我们看看你的循环。您最好的选择是使用fooId作为关键字保留地图中的对象(假设没有重复的对象)。
void mapFooBar(Map<Integer, Foo> fooMap, Map<Integer, Bar> barMap) {
for (Integer key : fooMap.keySet()) {
if (barMap.containsKey(key) {
Bar bar = barMap.get(key);
Foo foo = fooMap.get(key);
BeanUtils.copyProperties(foo, bar);
}
}
}
答案 3 :(得分:1)
看看Orika,一个高效的Java对象到对象映射
答案 4 :(得分:1)
在Java 1.8中,您可以这样写:
void mapFooBar(List<Foo> fooList, List<Bar> barList) {
Map<Integer, String> barMap = new HashMap<Integer, String>();
barList.stream()
.forEach(bar -> barMap.put(bar.fooId, bar.name));
fooList.stream()
// replaces if statement
.filter(foo -> barMap.containsKey(foo.id))
// update the bar name
.forEach(foo -> {
foo.barName = barMap.get(foo.id);
});
}
答案 5 :(得分:0)
您可以使用HashMap存储所有Foo对象,其id为key。
然后遍历Bar列表并直接访问你想要的HashMap位置
答案 6 :(得分:0)
有各种对象映射库旨在解决此问题。您可以查看的一个特别是ModelMapper。