ConcurrentHashMap JDK 8 when to use computeIfPresent

江枫思渺然 提交于 2019-12-03 08:42:51

问题


The new version of Concurrent Hash Map of jdk 8 has two new Methods.

computeIfAbsent

computeIfPresent

putIfAbsent - Old method

I understand the use cases of putIfAbsent and computeIfAbsent. But i am not sure of the scenarios when i will use computeIfPresent. Also why do i need putIfAbsent if i have computeIfPresent now. putIfAbsent do create atleast one extra instance of the value.

Is the reason is only to have backward compatability?


回答1:


As mentioned in the other answer: Methods will always be kept for backward compatibility, even if there are new, more "powerful" methods introduced.

Concerning the use case for computeIfPresent: It may be hard to find an example that is small enough to not look contrived and still be convincing. In general, the intention of this method is to update an existing value in any form.

One example could be a (constrained) word count: For a given set of words, one stores an initial count of 0 in the map. Then, a sequence of words is processed: Whenever one finds a word from the initial set, its count is increased by 1:

import java.util.LinkedHashMap;
import java.util.Map;

public class ComputeIfPresentExample 
{
    public static void main(String[] args) 
    {
        Map<String, Integer> wordCounts = new LinkedHashMap<String, Integer>();

        String s = 
            "Lorem ipsum dolor sit amet consetetur iam nonumy sadipscing " + 
            "elitr, sed diam nonumy eirmod tempor invidunt ut erat sed " + 
            "labore et dolore magna dolor sit amet aliquyam erat sed diam";

        wordCounts.put("sed", 0);
        wordCounts.put("erat", 0);

        for (String t : s.split(" "))
        {
            wordCounts.computeIfPresent(t, (k,v) -> v+1);
        }
        System.out.println(wordCounts);
    }
}

(Of course, things like this could be solved differently, but this is a rather frequent task in one or the other form, and the new method allows a rather concise and elegant solution)




回答2:


A common use case are maps with collections, like

Map<String, Collection<String>> strings = new HashMap<>();

computeIfAbsent and computeIfPresent are very handy operations for adding and removing elements to/from the collection. Here's an example that groups strings by their first char. Note that both the keys and the collections are created when necessary and cleaned it up when the collection becomes empty:

void addString(String a) {
    String index = a.substring(0, 1);
    strings.computeIfAbsent(index, ign -> new HashSet<>()).add(a);
}

void removeString(String a) {
    String index = a.substring(0, 1);
    strings.computeIfPresent(index, (k, c) -> {
        c.remove(a);
        return c.isEmpty() ? null : c;
    });
}

Example:

                         // {}
addString("a1");         // {a=[a1]}      <-- collection dynamically created
addString("a2");         // {a=[a1, a2]}
removeString("a1");      // {a=[a2]}
removeString("a2");      // {}            <-- both key and collection removed

This is extremely powerful in multithreading environments as ConcurrentMaps perform these operations atomically.

The remove operation can be a one-liner:

void removeString(String a) {
    String index = a.substring(0, 1);
    strings.computeIfPresent(index, (i, c) -> c.remove(a) && c.isEmpty() ? null : c);
}



回答3:


The JDK hardly ever breaks backwards compatibility. Because then you can not easily port or run software from an older version with the latest version.

You can run software compiled with an older version of the library with any version (meaning users that have the JRE installed) that still has those functions.




回答4:


I've used computeIfPresent as a null-safe way to fetch lowercase values from a map of strings.

String s = fields.computeIfPresent("foo", (k,v) -> v.toLowerCase())

Before computeIfPresent was available I'd have to do this:

String s = map.get("foo");
if (s != null) {
    s = s.toLowerCase();
}

Or this:

String s = map.containsKey("foo") ? map.get("foo").toLowerCase() : null;


来源:https://stackoverflow.com/questions/24872531/concurrenthashmap-jdk-8-when-to-use-computeifpresent

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!