3

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?

2
  • Are your two list the same size ? Each element in the first is in the second and vice-versa ? Are each element unique in your list ? Commented Sep 3, 2010 at 6:07
  • @Colin HEBERT. The size of both Lists are same. Each element in the first is there in the second list. For example, The first List has a PersonDetails VO with name "John" and description "John's description". The second List has a PersonDetails VO with same name "John" and address "Street1". I need to merge the two lists so that, I have a new list with name,address and description as "John", "John Description" and "Street1" Commented Sep 3, 2010 at 6:18

5 Answers 5

5

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;

}
Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

2

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

Comments

1

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

Comments

1
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.

2 Comments

good idea, but why not write data from vo2 to vo1, that would save many object creations?
@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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.