tags:

views:

233

answers:

5

Dear All, I need to join two Lists in Java. I've a list which has a VO that has a name and description. I've another list which has same VO type that has name and Address. The "name" is same. I need to create a List with this VO which has both name, address and description. The VO structure is

public class PersonDetails{
    private String name;
    private String description;
    private String address;
//getters and setters
}

Can someone please suggest me the best way to implement it?

+4  A: 

It depends:

If the lists contain both exactly the same data, you can sort them both by name, iterate over them en set the missing property.

If not, I would put the first list in a Map, with the name as key. Then iterate over the second list, look in the map for the VO and set the value. After that, just get all the value's out of the map again as a List.

public List<Vo> merge(List<Vo> list1, List<Vo> list2) {

    Map<String, Vo> tempMap = new HashMap<String, Vo>();

    for (Vo v : list1) {
        tempMap.put(v.name, v);
    }

    for (Vo vv : list2) {

        //The if is in case the 2 lists aren't filled with the same objects            
        if (tempMap.containsKey(vv.name)) {
            tempMap.get(vv.name).description = vv.description;
        } else {
            tempMap.put(vv.name, vv);
        }
    }

    return new ArrayList<Vo>(tempMap.values());

}

If the lists contain both EXACT the same VO (equal by name), you can use this.

public List<Vo> merge(List<Vo> list1, List<Vo> list2) {

    Collections.sort(list1, new Comparator<Vo>() {

        public int compare(Vo o1, Vo o2) {
            return o1.name.compareTo(o2.name);
        }
    });

    Collections.sort(list2, new Comparator<Vo>() {

        public int compare(Vo o1, Vo o2) {
            return o1.name.compareTo(o2.name);
        }
    });

    for(int i = 0; i < list1.size(); i++){
        list1.get(i).description = list2.get(i).description;
    }

    return list1;

}
Cid54
sounds like a winner to me
seanizer
+1  A: 

Go from list to HashMap, use the name string as key. So you can merge you data quite efficient.

atamanroman
+1  A: 
List<VO> list = new ArrayList<VO>();
for (VO vo1 : vo1List) {
   for (VO vo2 : vo2List) {
    if (vo1.getName().equals(vo2.getName())) {
        VO newVo = new VO();
        newVO.setName(vo1.getName());
        newVO.setDescription(vo1.getDescription());
        newVO.setAddress(vo2.getAddress);
        list.add(newVO);
        break;
    }
}

}

It's best that you sort both lists on name beforehand, it makes the double iteration faster.

nkr1pt
good idea, but why not write data from vo2 to vo1, that would save many object creations?
seanizer
@seanizer exactly, but the example was meant as a simple example to give the OP the idea of how to do it using a double loop.
nkr1pt
+2  A: 

I would put each list of the source VO lists in a map by name, create a set of both keys, iterate it and add a target VO to the result list.

In the example code, VO is the target VO, VOD is the source VO with description only, VOA is the source VO with address only:

List<VOD> descriptions = ...;
List<VOA> addresses = ...;
Map<String,String> description ByName = new HashMap<String,String>();
for (VOD description : descriptions) {
  descriptionByName.put(description.name, description.description);
}
Map<String,String> addressByName = new HashMap<String,String>();
for (VOA address: addresses ) {
  addressByName.put(address.name, address.address);
}

Set<String> allNames = new HashSet<String>();
allNames.addAll(descriptionByName.keySet());
allNames.addAll(addressByName.keySet());

List<VO> result = new ArrayList<VO>();
for (String name : allNames) {
  VO one = new VO();
  one.name = name;
  one.address = addressByName.get(name)
  one.description = descriptionByName.get(name)
  result.add(one);
}
Arne Burmeister
+1  A: 

Put all elements of the first list in a map, then merge the contents of the second list into it:

final List<PersonDetails> listWithAddress =
    new ArrayList<PersonDetails>();
final List<PersonDetails> listWithDescription =
    new ArrayList<PersonDetails>();
// fill both lists with data

final Map<String, PersonDetails> map =
    // map sorted by name, change to HashMap otherwise
    // (or to LinkHashMap if you need to preserve the order)
    new TreeMap<String, PersonDetails>();

for(final PersonDetails detailsWithAddress : listWithAddress){
    map.put(detailsWithAddress.getName(), detailsWithAddress);
}
for(final PersonDetails detailsWithDescription : listWithDescription){
    final PersonDetails retrieved =
        map.get(detailsWithDescription.getName());
    if(retrieved == null){
        map.put(detailsWithDescription.getName(),
            detailsWithDescription);
    } else{
        retrieved.setDescription(detailsWithDescription.getDescription());
    }
}
seanizer