简体   繁体   中英

Merge lists with common column using lambdas and streams in java

I have two scenarios with below two domain objects :

class A{
     String id;
      String name;
       String value;
      String val1;
      String val2;
 }

class PropVal{
String id;
String propVal1;
String propVal2;
String propVal3;
String propVal4;
 }

1) I have 4 lists

List<String> 1 = { id1,id2 ,id3}
List<String> 2 = { "one","two","three"}

Note- List 1 elements correspond to List 2 elements like id1 = "one" , id2 = "two" and so on

List<String> 3 =  { "one","two","three"}
List<String> 4 =  { 1,2,3}

Note- List 3 elements correspond to List 4 elements like "one" = 1 , "two" = 2 and so on

All values of these list correspond to properties of class A so more lists like above with all properties so may be cannot make map of just two above lists.

What i want is to merge these lists based on common field,ie, name ( values is List 2 & list 3) like

List<A> onjList = {[id=id1,name=one,value=1] , [id=id2,name=two,value=2] ,[id=id3,name=three,value=3]..... } 

2) I have two lists

List<A> onjList - {[id=id1,name=one,value=1] , [id=id2,name=two,value=2] ,[id=id3,name=three,value=3]..... } -----obtained from Step 1
List<PropVal> list 2 = { [id=id1,propVal1=w,propVal2=x,propVal3=y,propVal4=z] , [id=id2,propVal1=a,propVal2=b,propVal3=c,propVal4=d] ....}

I want a final list like

List<A> final List = {[id=id1,name=one,value=1,val1=w ,val2=x] , [id=id2,name= two,value = 2,val1 = a ,val2 = b]..... }

note val1 = propVal1 and val2 = propVal2.

What is the best way to do both of these scenarios ? Preferably using java 8 streams and lambdas ?

Your examples are misleading. Numbers don't make good variable names and all four lists are in the same order, but I assume, your question is supposed to imply that the first two list may have a different order than the other two, eg

List<String> aNames=Arrays.asList("one", "two", "three");
List<String> aIDs  =Arrays.asList("id1", "id2", "id3");

List<String> bNames =Arrays.asList("two", "one", "three");
List<String> bValues=Arrays.asList("2",   "1",   "3");

While merging all lists in one step is possible, the repeated linear search would yield an overall quadratic time complexity, so this is discouraged. Instead, merge two associated lists into a map, allowing efficient lookup, then, merge the other two with the map:

assert bNames.size()==bValues.size();
Map<String,String> bNameToValue = IntStream.range(0, bNames.size())
    .collect(HashMap::new, (m,i) -> m.put(bNames.get(i),bValues.get(i)), Map::putAll);

assert aNames.size()==aIDs.size();
List<A> list = IntStream.range(0, aNames.size())
    .mapToObj(i -> new A(aIDs.get(i), aNames.get(i), bNameToValue.get(aNames.get(i))))
    .collect(Collectors.toList());

The considerations for the second task are similar. If the list of PropVal elements is not in the same order, ie a lookup is needed, it's recommended to have a map, which implies that it might be simpler to let the previous step generate a map in the first place.

assert bNames.size()==bValues.size();
Map<String,String> bNameToValue = IntStream.range(0, bNames.size())
    .collect(HashMap::new, (m,i)->m.put(bNames.get(i),bValues.get(i)), Map::putAll);

assert aNames.size()==aIDs.size();
Map<String,A> idToA = IntStream.range(0, aNames.size())
    .mapToObj(i -> new A(aIDs.get(i), aNames.get(i), bNameToValue.get(aNames.get(i))))
    .collect(Collectors.toMap(A::getId, Function.identity()));

List<PropVal> list2 = …

then, if A is mutable:

list2.forEach(pVal -> {
    A a = idToA.get(pVal.id);
    a.setVal1(pVal.propVal1);
    a.setVal2(pVal.propVal2);
    a.setVal3(pVal.propVal3);
    a.setVal4(pVal.propVal4);
});

List<A> finalList = new ArrayList<>(idToA.values());

or if A is immutable:

List<A> finalList = list2.stream()
     .map(pVal -> {
        A a = idToA.get(pVal.id);
        return new A(pVal.id, a.getName(), a.getValue(),
            pVal.propVal1, pVal.propVal2, pVal.propVal3, pVal.propVal4);
        })
     .collect(Collectors.toList());

(note that this includes only those A instances into the list, for which a PropVal exists).

Please do not abuse java 8 features! You have data design drawbacks. Provide useful methods in your classes, migrate to suitable data structures. In your model it is easy to get inconsistent data.

Do not delegate all your problems to lambdas and streams.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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