Reputation: 35
Facing a challenge to come up with an efficient way of merging two ArrayLists of Maps.
The map looks like this:
{Username=User1, Role=Admin}
So one list looks like this:
List1 = [{Username=User1, Role=Admin},{Username=User2, Role=Auditor}]
and so on.
There is another list:
List 2 = [{Username=User1, Role=Integrator},{Username=User2, Role=Manager}]
Note: The users have different roles in different lists.
What i want to end up with is:
MergedList = [{Username=User1, Role=[Admin,Integrator]},{Username=User2, Role=[Auditor,Manager}]
Another Note: The actual list has 50,000 maps and each map has 20entries!! Just tried to keep it simple here.
Below are the stuff i tried. But failed.
Tried putAll
.
Tried merge
.
Tried something that I found in another post
map2.forEach((k, v) -> map3.merge(k, v, String::concat));
Upvotes: 2
Views: 424
Reputation: 11042
You can use Java Streams to achieve this:
Map<String, List<String>> result = Stream.concat(users1.stream(), users2.stream())
.collect(Collectors.groupingBy(m -> m.get("Username"), Collectors.mapping(m -> m.get("Role"), Collectors.toList())));
This groups all the users and collects their roles.
The result will be:
{User1=[Admin, Integrator], User2=[Auditor, Manager]}
Upvotes: 1
Reputation: 44398
With regard to the performance and massive amount of data, I recommend you to avoid any usage of java-stream (although it is quite quick itself) and the Map::merge
method.
Here you have to stick with the constructs closes to the JVM level and for-loops
are your friends, here is the simplest approach I am aware of that might work:
final Map<String, Set<String>> newMap = new HashMap<>();
for (Map<String, String> map: list) { // iterate the List<Map>
for (Entry<String, String> entry: map.entrySet()) { // iterate the entries
final String key = entry.getKey(); // get the entry's key
newMap.computeIfAbsent(key, k -> new HashSet<>()); // compute a new pair
newMap.get(key).add(entry.getValue()); // add a value in any case
}
}
Set
prevents duplicate values.
This solution assumes the following data structure. Slight variations are easy to apply to the solution above.
List<Map<String, String>> list = new ArrayList<>();
Map<String, String> map1 = new HashMap<>();
map1.put("User1", "Admin");
map1.put("User2", "Auditor");
Map<String, String> map2 = new HashMap<>();
map2.put("User1", "Integrator");
map2.put("User2", "Manager");
map2.put("User3", "Coffee machine");
list.add(map1);
list.add(map2);
Upvotes: 1