Java 11 here. I have a List<Foobar>
as well as a Map<Foobar,List<String>>
.
I would like to iterate over the list and:
- if the current
Foobar
is a key in the map, and a specific string ("Can't please everyone") to that entry's value list - if the current
Foobar
is not a key in the map, and it as a new key, with a value that is anArrayList
consisting of a single string with the same value
I can accomplish this like so:
List<Foobar> foobarList = getSomehow();
Map<Foobar,List<String>> foobarMap = getItSomehow();
String msg = "Can't please everyone";
for (Foobar fb : foobarList) {
if (foobarMap.containsKey(fb)) {
foobarMap.get(fb).add(msg);
} else {
foobarMap.put(fb, Collections.singletonList(msg));
}
}
This works great, but I'm trying to get this to work using the Java Stream API. My best attempt thus far:
List<Foobar> foobarList = getSomehow();
Map<Foobar,List<String>> foobarMap = getItSomehow();
String msg = "Can't please everyone";
foobarList.stream()
.filter(fb -> foobarMap.containsKey(fb))
.map(fb -> foobarMap.get(fb).add(msg))
.filter(fb -> !foobarMap.containsKey(fb))
.map(fb -> foobarMap.put(fb. Collections.singleton(msg));
Yields several compiler errors. Can anyone spot where I'm going awry?
CodePudding user response:
Streams are used either
- To modify the contents of the stream elements, or
- To produce another stream from it, or
- To iterate over the elements and do something that doesn't affect the elements of this stream.
Since your use case is the last type, the logical operation is simply forEach(..)
. (I know it is a dampener :-), but that is how the use case is.)
foobarList.forEach( fb -> {
if (foobarMap.containsKey(fb)) {
foobarMap.get(fb).add(msg);
} else {
foobarMap.put(fb, Collections.singletonList(msg));
}
} );
CodePudding user response:
As noticed by @Sree Kumar, you should use forEach()
.
However, I would suggest leveraging the Map.merge()
method:
foobarList.forEach(fb -> foobarMap.merge(fb, Collections.singletonList(msg),
(l1, l2) -> Stream.concat(l1.stream(), l2.stream()).toList()));