Map中的值自增自减或重新操作值的最优雅写法,无需调用get()和put(),包含HashMap compute()源码分析

您所在的位置:网站首页 集合运算加减 Map中的值自增自减或重新操作值的最优雅写法,无需调用get()和put(),包含HashMap compute()源码分析

Map中的值自增自减或重新操作值的最优雅写法,无需调用get()和put(),包含HashMap compute()源码分析

2024-07-11 19:33| 来源: 网络整理| 查看: 265

相信各位在开发的过程中总能遇见类似这样的需求:查询Map中的某一key值,如果有就将值加一,没有就put新的key值为1 (或对值进行其他操作)。

通常大多数人的写法是这样的:

@Test public void test1() { HashMap map = new HashMap(); map.put(1, 1); // {1=1} for (int i = 0; i threshold || (tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; // map是数组加链表或数组加红黑树的数据结构,所以first是链表上的第一个元素,如果firsh不为null则进如if if ((first = tab[i = (n - 1) & hash]) != null) { // 如果是TreeNode的子类(红黑树数据结构),则通过方法获取原Node if (first instanceof TreeNode) old = (t = (TreeNode)first).getTreeNode(hash, key); // 链表数据结构, else { // e用来指向链表的元素 Node e = first; K k; do { // 如果hash值相等 并且key值相等 并且(key不为null,equals方法为true),则获取到原Node if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { old = e; break; } // 记录链表的元素个数,用来之后判断是否超出阈值将链表转换成红黑树 ++binCount; } while ((e = e.next) != null); } } // oldvalue:原value V oldValue = (old == null) ? null : old.value; // v:根据我们实现的方法来计算新的value V v = remappingFunction.apply(key, oldValue); if (old != null) { if (v != null) { // 原map有key对应的键值对,则用计算出的新值赋值 old.value = v; // 元素被访问之后的后置处理, LinkedHashMap中有具体实现 afterNodeAccess(old); } else // 原map有key对应的键值对,但是新计算的值为null,删除原值。 removeNode(hash, key, null, false, true); } // 新value不为null else if (v != null) { // 原map没有key对应的键值对,并且当前桶使用红黑树数据结构存储,添加此键值对 if (t != null) t.putTreeVal(this, tab, hash, key, v); else { // 原map没有key对应的键值对,并且当前桶使用链表数据结构存储,添加此键值对 tab[i] = newNode(hash, key, v, first); // 查看是否到设置的链表转红黑树的阈值,到达则将链表转换成红黑树 if (binCount >= TREEIFY_THRESHOLD - 1) treeifyBin(tab, hash); } // 已知对hashMap结构修改的次数,结构修改指更改hashMap的映射数或以其他方式更改其内部结构(例:重新hash)的修改,此字段用于是hashMap的collectionview迭代器快速失败 ++modCount; // hashmap大小(键值对数) ++ ++size; // 添加新元素之后的后置处理, LinkedHashMap中有具体实现 afterNodeInsertion(true); } return v; } merge()方法类似与comoute()方法但是更简洁:

使用merge()实现上面需求

@Test public void test2() { HashMap map = new HashMap(); map.put(1, 1); // {1=1} for (int i = 0; i ++oldvalue); } System.out.println(map); // {0=1, 1=2, 2=1} }

第一个参数为key 第二个参数是一个newValue 第三个参数是对新值和旧值的操作 如果原value为null则添加key和第二个参数值newValue,如果原value不为null则赋值计算后的值(newValue为merge()方法的第二个参数值newValue)

类似compute()方法的其他方法:

computeIfPresent(): 如果map存在key,则对老value进行操作计算后赋值 computeIfAbsent(): 如果map不存在key,则对使用计算后的新value进行赋值

merge(),computeIfPresent(),computeIfAbsent()可以自行查看hashmap源码,和上面的compute()源码类似。

到此我们对JDK8中新加入的几种对hashMap的操作的方法就学习完了,这几种方法可以让我们更加便捷的对map中的key-value进行操作,省去了先get在put的繁琐操作,让我们在开发的过程中使代码更加简洁流畅。

如果此篇文章对你有帮助可以关注我呦!我会继续更新自己平时所学习的java知识!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3