HashMap的computeIfAbsent与computeIfPresent

本文通过LeetCode第49题的解题思路,探讨HashMap的computeIfAbsent和computeIfPresent方法。computeIfAbsent在键存在且value非空时返回value,否则根据Function提供新值。当键存在且value非空时,computeIfPresent会用BiFunction更新value,若返回null则删除节点。这两个方法常用于动态更新Map中的值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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<List<String>> groupAnagrams(String[] strs) {
        if(strs == null || strs.length == 0) return new ArrayList<>();
        Map<String, List<String>> map = new HashMap<>();
        for(String s : strs){
            String k = hash(s);
            map.computeIfAbsent(k, s1 -> new ArrayList<>()).add(s);
//            List<String> 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<? super K, ? extends V> mappingFunction) {
        if (mappingFunction == null)
            throw new NullPointerException();
        int hash = hash(key); //计算hash
        Node<K,V>[] tab; Node<K,V> first; int n, i;
        int binCount = 0;
        TreeNode<K,V> t = null;
        Node<K,V> 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<K,V>)first).getTreeNode(hash, key);
            else {
                Node<K,V> 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<? super K, ? super V, ? extends V> remappingFunction) {
        if (remappingFunction == null)
            throw new NullPointerException();
        Node<K,V> 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的键值对的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值