ConcurrentHashMap JDK 8 when to use computeIfPresent

后端 未结 4 1329
粉色の甜心
粉色の甜心 2021-02-01 05:25

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

computeIfAbsent

computeIfPresent

putIfAbs

4条回答
  •  清酒与你
    2021-02-01 06:12

    A common use case are maps with collections, like

    Map> strings = new HashMap<>();
    

    computeIfAbsent and computeIfPresent are very handy operations for adding and removing elements to/from the collection. Not least because unlike put(), the compute*() methods return the current value (whether it was just created or not). 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);
    }
    

    So once again in short:

    Map> map = new ConcurrentHashMap<>();
    map.computeIfAbsent(key, i -> ConcurrentHashMap.newKeySet()).add(value);
    map.computeIfPresent(key, (i, s) -> s.remove(value) && s.isEmpty() ? null : s);
    

提交回复
热议问题