HashMap的computeIfAbsent与computeIfPresent

LeetCode:49
Given an array of strings, group anagrams together.

Example:

Input: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Output:
[
[“ate”,”eat”,”tea”],
[“nat”,”tan”],
[“bat”]
]
Note:

  • All inputs will be in lowercase.
  • The order of your output does not matter.

这是LeetCode的第49题,有一个巧妙的解题思路是,利用hash,字母相同的字符串让其hash相同。

    public List> groupAnagrams(String[] strs) {
        if(strs == null || strs.length == 0) return new ArrayList<>();
        Map> map = new HashMap<>();
        for(String s : strs){
            String k = hash(s);
            map.computeIfAbsent(k, s1 -> new ArrayList<>()).add(s);
//            List value = map.get(k);
//            if(value == null) map.put(k, new ArrayList<>());
//            value.add(s);
        }
        return new ArrayList<>(map.values());
    }

    private String hash(String s){
        int[] num = new int[26];
        for(char c : s.toCharArray()){
            num[c-'a']++;
        }
        return Arrays.toString(num);
    }

这里借此题想说的是HashMap的computeIfAbsent与computeIfPresent

computeIfAbsent

    @Override
    public V computeIfAbsent(K key,
                             Function mappingFunction) {
        if (mappingFunction == null)
            throw new NullPointerException();
        int hash = hash(key); //计算hash
        Node[] tab; Node first; int n, i;
        int binCount = 0;
        TreeNode t = null;
        Node old = null;
        // 如果为初始化则先进行初始化,
        // resize()方法在table为空时执行初始化逻辑
        if (size > threshold || (tab = table) == null ||
            (n = tab.length) == 0)
            n = (tab = resize()).length;
        // 下面的逻辑就是通过key找到节点node
        if ((first = tab[i = (n - 1) & hash]) != null) {
            if (first instanceof TreeNode)
                old = (t = (TreeNode)first).getTreeNode(hash, key);
            else {
                Node e = first; K k;
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k)))) {
                        old = e;
                        break;
                    }
                    ++binCount;
                } while ((e = e.next) != null);
            }
            V oldValue;
            // 如果key存在且其value!=null,则返回该value
            if (old != null && (oldValue = old.value) != null) {
                afterNodeAccess(old);
                return oldValue;
            }
        }
        // 下面的逻辑是:如果没找到则新建节点,
        // 节点value为Function返回值;如果找到但value为null,
        // 则将Function返回值作为其value
        V v = mappingFunction.apply(key);
        if (v == null) {
            return null;
        } else if (old != null) {
            old.value = v;
            afterNodeAccess(old);
            return v;
        }
        else if (t != null)
            t.putTreeVal(this, tab, hash, key, v);
        else {
            tab[i] = newNode(hash, key, v, first);
            if (binCount >= TREEIFY_THRESHOLD - 1)
                treeifyBin(tab, hash);
        }
        ++modCount;
        ++size;
        afterNodeInsertion(true);
        return v;
    }

总结:

  • 存在且value不为null,则返回value
  • 不满足上述条件下,先检查Function返回值,若为null,返回null
  • 存在但value为null,则将Function返回值作为value,返回value
  • 不存在,新建节点,将Function返回值作为value,返回value

    使用场景:从map中获取所需要的value,若其为null,就用准备好的值即Function的返回值,就像上面那题的用法那样

computeIfPresent

    public V computeIfPresent(K key,
                              BiFunction remappingFunction) {
        if (remappingFunction == null)
            throw new NullPointerException();
        Node e; V oldValue;
        int hash = hash(key);
        if ((e = getNode(hash, key)) != null &&
            (oldValue = e.value) != null) {
            V v = remappingFunction.apply(key, oldValue);
            if (v != null) {
                e.value = v;
                afterNodeAccess(e);
                return v;
            }
            else
                removeNode(hash, key, null, false, true);
        }
        return null;
    }

总结:

  • 存在且value不为null:1,BiFunction返回值为null,删除该节点;2,BiFunction返回值不为null,作为新value,返回其值
  • 不存在或其value为null,返回null

    使用场景:更新map中存在的且其value值不为null的键值对的值

你可能感兴趣的:(算法,集合)