Reputation: 19
I have two lists of Map<String, Object>
as shown below:
List1=[ {ID=1, actor="A", film="AA"},
{ID=1, actor="B", film="AA"} ]
List2={ [ID = 1, director="C"] }
Result = { [ID=1, actor="A", film="AA", director="C"],
[ID=1, actor="B", film="AA", director="C"] }
I want to use the Stream
class in Java 8 to join these lists.
How do I join the to get the value of Result shown?
Is the Stream
class in Java 8 fast and stable if List1
and List2
are very big?
Upvotes: 1
Views: 2627
Reputation: 16938
If performance matters, you should first build an index of directors:
Map<Object, Object> directors = list2.stream()
.collect(Collectors.toMap(m -> m.get("ID"), m -> m.get("director")));
Then you can merge the directors to the list entries easily:
list1.stream().forEach(m -> m.put("director", directors.get(m.get("ID"))));
Accesing the director via a Map
will be faster than searching the director for each list entry.
Upvotes: 1
Reputation: 622
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);
Upvotes: 1