-1

I followed many such links Merging two Maps, but unable to solve the issue yet.

I have two Maps List<Map<String, Object>> - This map contains acc_num, parent_acc_num, crte_dt, rnwl_dt, userid etc and other map contains acc_num and isActive (This is more refinement from 1st map).

I wanted to create/combine these two maps and create final map which conatins acc_num, parent_acc_num, crte_dt, rnwl_dt, userid + isActive details.

How can I do that ?

Below is the sample Data. The only issue is both are List of Map, how to iterate one over another ?

{CRTE_DT=2017-06-22, USER_ID=ABC, ACC_NUM=9449, RNWL_DT=2017-06-22, PARENT_ACC_NO=9449}

{ACC_NUM=9449, IS_ACTIVE=false}

Another Query: If below works then may not need to do calculations

I have the below Oracle query using 12c, I need the way to check in query itself if

  1. If CreatedDate + 30 days > Sysdate then show column having true ---> In Trail
  2. If CreatedDate + 30 days < Sysdate then show column having false ---> Out of Trail Period

"select cust.acc_num, third.parent_acc_id, cust.crte_dt,cust.updated_dt ,cust.crte_user_id from CUST_ACCT cust, ThirdParty_third third " + "where cust.updated_dt is null and cust.CRTE_DT < sysdate " + "and cust.acc_num = third.third_code and is_actv = ? union " + "select cust.acc_num, third.parent_acc_id, cust.crte_dt,cust.updated_dt, cust.crte_user_id from CUST_ACCT cust, ThirdParty_third third " + "where ( cust.updated_dt is not null and cust.updated_dt < sysdate ) " + "and cust.acc_num = third.third_code and is_actv = ? ";

Jeff Cook
  • 7,956
  • 36
  • 115
  • 186
  • 2
    Two maps or two lists? How do you want to merge `acc_num`? What have you tried? Where are you stuck? – shmosel Jul 25 '18 at 21:27
  • yes using account No, Both are Lists of Map – Jeff Cook Jul 25 '18 at 21:29
  • For each map value object is different and if you want to merge the maps than you would need a new type of object which holds both of the previous ones' data. Show us those objects. Also, is the list containing 2 elements? If so, why do you need a list? – user1803551 Jul 26 '18 at 07:57

3 Answers3

1

Assuming your list contains only two maps and they are both mutable. What you can do is add all mappings of the second map to the first one if and only if the second map has the mapping ACC_NUM equal to the first one.

final List<Map<String, Object>> maps = ...;

if (Optional.ofNullable(map.get(1).get("ACC_NUM")).filter(acc_num -> acc_num.equals(map.get(0).get("ACC_NUM"))).isPresent())
{
    map.get(0).putAll(map.get(1));
}

EDIT

final List<Map<String, Object>> l1 = ...;
final List<Map<String, Object>> l2 = ...;

final List<Map<String, Object>> result = l1.stream()
    .map(map ->
    {
      final Map<String, Object> r = new HashMap<>(map);
      l2.stream()
          .filter(map2 -> Objects.equals(map.get("ACC_NUM"), map2.get("ACC_NUM")))
          .findFirst()
          .map(map2 -> map2.get("IS_ACTIVE"))
          .ifPresent(is_active -> map.put("IS_ACTIVE", is_active));
      return r;
    })
    .collect(Collectors.toList());
marsouf
  • 1,107
  • 8
  • 15
  • @Prateek you can check my edit, it is partly equivalent to [Aomine's answer](https://stackoverflow.com/questions/51527885/how-to-combine-two-different-map-in-java#51548174). – marsouf Jul 27 '18 at 08:43
  • @ marsouf - Thank you so much. +1, Could you also post answer without java 8? – Jeff Cook Jul 28 '18 at 15:01
1

Here's one way to go about it:

List<Map<String, Object>> map3 = new ArrayList<>();
l1.forEach(map -> {
      // clone the map to avoid mutating existing maps
     Map<String, Object> temp = new HashMap<>(map);

     // get the corresponding match in the second list
     Optional<Object> value = l2.stream()
             .filter(m -> m.containsValue(map.get("ACC_NUM")))
             .findFirst().map(c -> c.get("IS_ACTIVE"));


     temp.put("IS_ACTIVE", value.get());  // insert the new entry
     map3.add(temp); // add the new map to the accumulator
});

This essentially enumerates over each map within l1 (the first list) and clones the entire map into a new map instance and simply insert a new entry into this new map where the key is "IS_ACTIVE" and the value is what we find in l2 (the second list).

This solution assumes there will always be a corresponding match in l2 hence the call to get() on the Optional<T> result. if however, that is not the case then you may use Optional#orElse to provide a default value or if the value is not found you simply don't want to add the entry into the map at all, consider using Optional#isPresent prior to adding to the map.

Further, I'd recommend going through Guide To Java 8 Optional to familiarise yourself with the Optional API and of course the java documentation!

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
  • I like that this uses the new stream APIs :-) - but I think this may be O(n*m), while mine, old-fashioned as it is, should be only O(m+n) ... – moilejter Jul 27 '18 at 01:45
0

I would create a Map<Integer,Map<String,Object>> to help things out. "acct_num" is the key that is common to both your maps, so you will use that to match them up.
Steps:

  • iterate over first list, adding each element to the map using its acc_num as the key.
  • iterate over second list, using acct_num value of each element to find matching element in map, then add "is_active" pair from second list to value you just found in map.
  • get values() from your helper map, and you have a list of maps with values merged.

The code would look something like this:

a = [CRTE_DT:"2017-06-22", USER_ID:"ABC", ACC_NUM:9449, RNWL_DT:"2017-06-22", PARENT_ACC_NO:9449]
b = [ACC_NUM:9449, IS_ACTIVE:false]
list1 = [a]
list2 = [b]
c = new HashMap<Integer,Map<String,Object>>()
for ( Map<String,Object> r : list1 ) { 
    c.put(r.get("ACC_NUM"),r) 
}
for (Map<String,Object> r : list2 ) { 
    d = c.get(r.get("ACC_NUM")); 
    if (d != null) d.putAll(r); 
}

groovy:000> c
===> {9449={CRTE_DT=2017-06-22, USER_ID=ABC, ACC_NUM=9449, RNWL_DT=2017-06-22, PARENT_ACC_NO=9449, IS_ACTIVE=false}}
moilejter
  • 958
  • 8
  • 9