Question

I'm looking for an efficient design pattern to map one list of objects to another list of objects with zero-or-one-to-one relationships between them. I realize this sort of thing is typically done in a relational database, but in this particular case it really needs to be done in the Java application...

Let's say the first list contains Foo objects (i.e. List<Foo>):

public class Foo {
    public Integer id;
    public String barName;
}

And the second list contains Bar objects (i.e. List<Bar>):

public class Bar {
    public Integer fooId;
    public String name;
}

How can I most efficiently map all name properties from Bar to the Foo object where Bar.fooId equals Foo.id?

The best I can think of is this:

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

EDIT: Based on several answers, I have improved my code as follows:

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

Is there a better way?

No correct solution

OTHER TIPS

I think what you are looking for is something like Apache BeanUtils or Springs implementation. Just make sure the properties are named the same between the 2 objects you want to copy the data between. So taking your code:

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

Now that the copy is done lets look at your loop. Your best bet would be to keep the Objects in Maps using fooId as the key (assuming no objects duplicated).

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

This has complexity of N * M that means if you have 5 foo and 8 bar it would have to execute loop for 40 times

class Container{

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

}

if you use Map<Integer, Container> it would be N + M (5 + 8 = 13 times)

iterate through both list once and map it with id


Also See

Take a look at Orika, an efficient Java Object to Object Mapping

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

In Java 1.8 you can write it like this:

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

Hmm. Assuming the "primary keys" were unique I might convert the list of Bar to a map with fooId as the key and either whole object or the name as the value. Then I would iterate through the list of Foo and see whether the id property existed in the map. If it did I would map the bar.name to foo.barName;

You could use a HashMap to store all Foo objects, with their id as key.

Then loop through Bar list and access directly HashMap position you want

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top