简体   繁体   中英

Java 8: Change the values of an EntrySet stream

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 want getItems() to return all the items, but with the strings parsed using the renderTags(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?

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())));
}

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.

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.

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.

Since Java 9 you can also do:

Entry<String, String> entry = Map.entry("a", "b");

In your Map it would be used like this:

Map<Instant, String> getItems() {
    return items.entrySet()
            .stream()
            .map(entry -> Map.entry(entry.getKey(), renderTags(entry.getValue())))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM