Java 8: Change the values of an EntrySet stream
Solution 1
If you want a Map
as result:
Map<Instant, String> getItems() {
return items.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> renderTags(e.getValue())));
}
Solution 2
If you want to modify an existing map instead of generating the new one (as in your example), there's no need to use the stream at all. Use Map.replaceAll
:
items.replaceAll((k, v) -> renderTags(v));
return items;
If you want to keep the original map unchanged, consult other answers.
Solution 3
You can try it this way with Collectors.toMap()
:
Map<Instant, String> getItems() {
return items.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> renderTags(entry.getValue())
));
}
By the way, if the name says simply "get", you shouldn't generally transform it in there. One expects a getter to be simple and not costy at all.
Solution 4
An alternative could be
Map<Instant, String> getItems() {
return items.entrySet().stream()
.peek(entry -> entry.setValue(renderTags(entry.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey,e -> e.getValue()));
}
Useful if you have to perform updates on the stream before collect call.
Ruckus T-Boom
Updated on June 30, 2020Comments
-
Ruckus T-Boom almost 4 years
I have the following setup:
Map<Instant, String> items; ... String renderTags(String text) { // Renders markup tags in a string to human readable form } ... <?> getItems() { // Here is where I need help }
My problems is, the strings that are the values of the
items
map are marked up with tags. I wantgetItems()
to return all the items, but with the strings parsed using therenderTags(String)
method. Something like:// Doesn't work items.entrySet().stream().map(e -> e.setValue(renderTags(e.getValue())));
What is the most effective way to do this?
-
Vlasec almost 9 yearsOh well, you were almost a full minute faster :/
-
Ruckus T-Boom almost 9 yearsCan either of you tell me why I'd get a
Cannot resolve method 'getKey'
on the lineMap.Entry::getKey
? -
Didier L almost 9 yearsAre you sure that your
Map
import is reallyjava.util.Map
? -
Ruckus T-Boom almost 9 years@DidierL I just checked to make sure and it is.
-
Ruckus T-Boom almost 9 yearsSorry, I figured it out. It was a typo in the method return type, that was somehow showing up as the error I mentioned. Fixed that and it works great :)
-
Ruckus T-Boom almost 9 yearsNot what I need here (the new map is just for display purposes), but I didn't know that, so I'll file it away for later. Thanks!
-
Ruckus T-Boom almost 9 yearsWhat are the advantages/disadvantages of doing it this way versus the way shown in the accepted answer?
-
Max almost 9 yearsit depends on context (not the one of the question)... I havn't yet used the peek method but I keep in mind it exists.
-
Ruckus T-Boom almost 9 yearsSounds good. I use it a lot for debugging (just shooting the result to System.err), but I've never thought to use it like this.
-
Max almost 9 yearsMe too :) And I havn't been in the case of a sequence of changes to apply to a collection or map.
-
Vlasec almost 9 yearsYep, to the victor go the spoils.
-
Vlasec almost 9 yearsWhat does exactly happen when you modify an entry? I think it changes the map and the action called in peek should be non-interfering. It is good for logs, but if I got it, it shouldn't be used this way, as far as I know.
-
Max almost 9 yearsYou have to think your map with references of objects. Updating the value of an entry doesn't affect the map itself (nor the result of hashcode and equals mechanism used on keys for storing elements).
-
Max almost 9 yearsAnd this remark is valid for collections in general. When iterating on a collection, you can update the elements inside. Not the collection itself.
-
Nicholas DiPiazza over 6 yearsyeah this is the solution i needed. if you don't want a new map, use this.
-
рüффп over 4 years+1 for giving a solution to alter the original map. Exactly what I was looking for. Note that with the accepted answer it can also work but the original Map must be merged with the altered keys like
oMap.putAll(alteredMap)
. Method peek prevent to do this. -
user1803551 about 2 yearsDon't perform operations in
peek
, they are not guaranteed to execute. It's only for debugging purposes. -
Max almost 2 yearsYes, definitely, I update my answer.
-
user1803551 almost 2 yearsThat doesn't help at all.
peek
should not perform any operation with side effects. It's meant to be used to print intermediate results. -
Max almost 2 yearsbaeldung.com/java-streams-peek-api. the last paragraph describes clearly the same use case in a non debugging context: "we want to alter the inner state of an element". Even if I try to avoid this situation, I conceive it can occurs. That's why I may have used at least once in my carrer.