Reputation: 3904
I have a list of maps with non distinctive keys and like to modify each map value with Streaming API. The result should be a new list, the original one has to remain unchanged.
Example data:
// [ {jpg=firstImage.jpg, png=firstImage.png}, {jpg=secondImage.jpg, png=secondImage.png} ]
Map<String, String> map1 = new HashMap<>();
map1.put("jpg", "firstImage.jpg");
map1.put("png", "firstImage.png");
Map<String, String> map2 = new HashMap<>();
map2.put("jpg", "secondImage.jpg");
map2.put("png", "secondImage.png");
List<Map<String, String>> list = new ArrayList<>();
list.add(map1);
list.add(map2);
Let's assume I want to convert the filename to upper case. With distinctive values I could do the following:
Map<String, String> copy = list.stream()
.flatMap(e -> e.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toUpperCase()));
But flatMap does not work when keys aren't distinctive, and it would destroy my List<Map<String, String>>
structure. I know that the structure is bad, but I can't change it.
Expected outcome:
// [ {jpg=FIRSTIMAGE.JPG, png=FIRSTIMAGE.PNG}, {jpg=SECONDIMAGE.JPG, png=SECONDIMAGE.PNG} ]
I'd like to achieve this with Streaming API and avoid nested loops if possible.
Upvotes: 1
Views: 115
Reputation: 86242
Here’s an option
list.forEach(map -> map.replaceAll((t, f) -> f.toUpperCase()));
I am modifying the existing maps in your list. And it’s not using streams.
Edit: Thanks to VGR for the great simplification.
Edit: Since you need to leave your original structure unmodified, Eugene’s solution is fine. You may also apply replaceAll()
on a copy. One example:
List<Map<String, String>> result = new ArrayList<>(list);
list.replaceAll(m -> {
Map<String, String> newMap = new HashMap<>(m);
newMap.replaceAll((t, f) -> f.toUpperCase());
return newMap;
});
Or yet a different approach, this one with a stream:
List<Map<String, String>> result = list.stream()
.map(m -> {
Map<String, String> newMap = new HashMap<>(m);
newMap.replaceAll((t, f) -> f.toUpperCase());
return newMap;
})
.collect(Collectors.toList());
Which to prefer, I’d say it’s mostly a matter of taste.
Upvotes: 1
Reputation: 120848
You can't use flatMap
, because this way you would concat all Entries in a single Stream and thus loose the possibility to get them back.
You need to convert each individual element from your List
, like this for example:
List<Map<String, String>> result = list.stream()
.map(map -> map.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().toUpperCase())))
.collect(Collectors.toList());
System.out.println(result);
// [{jpg=FIRSTIMAGE.JPG, png=FIRSTIMAGE.PNG}, {jpg=SECONDIMAGE.JPG, png=SECONDIMAGE.PNG}]
Upvotes: 3