Ah now I understand what you want :)
I don't know if there is a better way with streams but here is a solution which would work.
List<Map<String, String>> resultList = l1.stream()
.map(m1 -> {
Map<String, String> map = new HashMap<>();
map.putAll(m1);
l2.stream()
.filter(m2 -> map.get("ID").equals(m2.get("ID")))
.findFirst()
.ifPresent(m2 -> map.put("director", m2.get("director")));
return map;
})
.collect(Collectors.toList());
The above code generates a new List resultList and does not modify the other lists List1 and List2. If it does not matter if List1 gets modified or not you could do it in a cleaner, more readable way.
l1.forEach(m1 -> l2.stream()
.filter(m2 -> m1.get("ID").equals(m2.get("ID")))
.findFirst()
.ifPresent(m2 -> m1.putIfAbsent("director", m2.get("director"))));
This way the entries of list1 get modified. So with the above example list1 is becomes the joined list. But it's actually good practice to have methods without any side effects. So I would not prefer the above example.
I would recommend a method getJoinedList which returns a new List and does not modify the other lists. And in this case I would not use streams but the old-fashioned for-loop.
private static List<Map<String, String>> getJoinedList(
List<Map<String, String>> l1, List<Map<String, String>> l2) {
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, String> m1 : l1) {
Map<String, String> newMap = new HashMap<>();
newMap.putAll(m1);
for (Map<String, String> m2 : l2) {
if (m1.get("ID").equals(m2.get("ID"))) {
newMap.put("director", m2.get("director"));
break;
}
}
result.add(newMap);
}
return result;
}
Then you just can call the method like this.
List<Map<String, String>> joinedList = getJoinedList(l1, l2);
list1.addAll(list2);Maps in the first list. Is it theactor? How about the key for theMaps in the second list?