繁体   English   中英

Java:将一个对象列表的属性映射到另一个对象的最有效方法

[英]Java: Most efficient way to map properties of one list of objects to another

我正在寻找一种有效的设计模式,以将一个对象列表映射到另一个对象列表,并且它们之间具有零或一对一的关系。 我意识到这种事情通常是在关系数据库中完成的,但是在这种特殊情况下,确实需要在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;
}

如何最有效地将Bar所有name属性映射到Bar.fooId等于Foo.idFoo对象?

我能想到的最好的是:

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;
        }
    }
}

编辑:基于几个答案,我改进了我的代码,如下所示:

void mapFooBar(List<Foo> fooList, List<Bar> barList) {
    Map<Integer, String> barMap = new HashMap<Integer, String>();
    for (Bar bar : barList)
        barMap.put(bar.fooId, bar.name);

    for (Foo foo : fooList)
        if (barMap.containsKey(foo.id)) foo.barName = barMap.get(foo.id);
}

有没有更好的办法?

复杂度为N * M ,这意味着如果您有5个foo和8个bar,则必须执行40次循环

class Container{

  List<Foo> foos;
  List<Bar> bars;

}

如果使用Map<Integer, Container> ,则为N + M (5 + 8 = 13次)

遍历两个列表一次并用id映射它


另请参阅

嗯。 假设“主键”是唯一的,我可以将Bar的列表转换为以fooId作为键,整个对象或名称作为值的映射。 然后,我将遍历Foo的列表,并查看id属性是否存在于地图中。 如果可以,我会将bar.name映射到foo.barName;。

我认为您正在寻找的是类似Apache BeanUtilsSprings的实现。 只要确保要在两个对象之间复制数据的属性名称相同即可。 所以拿你的代码:

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);
    }
  }
}

看看Orika,这是一种高效的Java对象到对象的映射

https://github.com/orika-mapper/orika

在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);
        });
}

您可以使用HashMap存储所有Foo对象,并将其id作为键。

然后遍历栏列表并直接访问所需的HashMap位置

有各种各样的对象映射库旨在解决此问题。 您可能要签出的特别之​​一是ModelMapper

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM