[HashMap] 1.merge 2.compute 3.包装类小坑 4.computeIfAbsent 5.LinkedHashMap 6.removeIf 7.ImmutableMap 8.

本文主要是介绍[HashMap] 1.merge 2.compute 3.包装类小坑 4.computeIfAbsent 5.LinkedHashMap 6.removeIf 7.ImmutableMap 8.,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 1)merge()

我理解这个merge可以废弃了,完全使用conpute代替!!!

// 名字其实很直观:合并数量。 不存在时,当然会追加。

// 与compute的区别:merge接收的是3个参数。 而 compute接收的是2个参数

场景:我通过多个途径获取了物品a,发给客户端前需要合并下数量

package org.example.basic;import java.util.HashMap;
import java.util.Map;public class TestMerge {public static void main(String[] args) {Map<Integer, Integer> idNumMap = new HashMap<>();idNumMap.put(1, 10);idNumMap.put(2, 20);idNumMap.put(3, 30);System.out.println(idNumMap);// 测试存在,则累计mergeAttr(idNumMap, 1, 30);System.out.println(idNumMap);// 测试key不存在,则加入mergeAttr(idNumMap, 4, 40);System.out.println(idNumMap);}public static Map<Integer, Integer> mergeAttr(Map<Integer, Integer> idNumMap, int id, int num) {// 注意第3个参数lambda表达式idNumMap.merge(id, num, Integer::sum);return idNumMap;}
}/*
//原始
{1=10, 2=20, 3=30}// merge一次后
{1=40, 2=20, 3=30}// 不存在则插入
{1=40, 2=20, 3=30, 4=40}*/

例子2:每个等级有个属性加成,加到一起

// 其实跟例子1是一样的,只不过这是真实案例,相当于

// 玩家身上有多个buff,buff1添加移速1,攻击2   buff2添加移速5,暴击10   这样子计算玩家总属

// 性时,就可以把多个buff的效果合并到一起。

package org.example.ch2;import java.util.HashMap;
import java.util.Map;public class Main2 {public static void main(String[] args) {int[] attribute = new int[]{1, 2, 3, 4, 1, 2};float[] value = new float[]{1, 1, 1, 1, 1, 1};Map<Integer, Float> map = new HashMap<>();for (int i = 0; i < attribute.length; i++) {map.merge(attribute[i], value[i], (o, n) -> o + n);}System.out.println(map);}
}/*
{1=2.0, 2=2.0, 3=1.0, 4=1.0}*/

2)compute方法(存在此key则修改,不存在,则会进行插入) 

// 含义是:替换,计算嘛,计算出来一个新的,替换掉旧的。

例子:玩家一下子获得多个道具包,在展示时,需要进行下数量合并:

包1包含:金币100个  黄金 100,

包2包含:金币200个  格斗币 300

那给客户端展示时,不可能这样子铺开展示,而是:展示的金币应该是300而不是出现2个金币,.这时就需要合并下。

package org.example.testMerge;import com.google.common.collect.Lists;
import com.google.common.collect.Maps;import java.util.List;
import java.util.Map;public class Main {public static void main(String[] args) {Map<Integer, AwardItem> map = Maps.newHashMap();map.put(1, new AwardItem(1, 10, 5));map.put(2, new AwardItem(1, 20, 50));List<AwardItem> computeRet = compute(map);System.out.println(computeRet);}public static List<AwardItem> compute(Map<Integer, AwardItem> map) {// 这个记录下合并的中间结果Map<Integer, AwardItem> awardSnAwardItemMap = Maps.newHashMap();for (AwardItem item : map.values()) {awardSnAwardItemMap.compute(item.getSn(), (k, v) -> {// 没有的以map中的为准,这样子这个awardSnAwardItemMap也会插入一份if (v == null) {return item;}// 有的,则累加到一起return new AwardItem(item.getSn(), v.getFreeNum() + item.getFreeNum(), v.getBindNum() + item.getBindNum());});}return Lists.newArrayList(awardSnAwardItemMap.values());}
}/*
[AwardItem(sn=1, freeNum=30, bindNum=55)]*/

例子2:这个其实更简单一点,这个Map中存的是普通类型的Integer

package org.example.basic;import java.util.HashMap;
import java.util.Map;public class TestCompute {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("Shoes", 200);map.put("Bag", 300);map.put("Pant", 150);int num = cal(map, "Shoes1");System.out.println(map);System.out.println(num);}public static int cal(Map<String, Integer> map, String key) {// 如果key不存在,则会插入这个key,并且对应的value是lambda的返回值// 如果存在,则把对应的value,修改为返回值return map.compute(key, (k, v) -> {if (v == null) {return -1;}return v - 100;});}
}/*
{Pant=150, Shoes1=-1, Bag=300, Shoes=200}
-1*/

例子3:玩家过这个关卡需要4个小关卡,每个关卡中记录每个人的得分,

这一关通关时,需要合并下之前的分数,其实就可以再次用上compute

例子4:一种merge和compute等价写法 // 可以看出来这2个有点像,但是我可以总结出:感觉merge更适合普通类型,不然怎么merge(相加)呢? conpute则可以用于复杂类型,如:直接处理的是AwardItem

package org.example.basic;import com.google.common.collect.Maps;import java.util.Map;public class Test1 {public static void main(String[] args) {Map<Integer, Integer> map = Maps.newHashMap();map.put(1, 1);// 方式1(存在key为2的,则把3合并上去,不然就返回3)map.merge(2, 3, Integer::sum);// 方式2(用一个新值填补)merge(map, 2, 3);System.out.println(map);}static public void merge(Map<Integer, Integer> map, int key, int value) {map.compute(key, (k, v) -> {if (v == null) {return value;}return v + value;});}
}

3)从Map中获取信息时包装类的一个细节 1.用int取值则报异常 2.用Integer取值则是null

package org.example.testmap;import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) {Param p = new Param();// 异常int o1 = p.get("1");// 正常Integer o2 = p.get("2");System.out.println(o2); // null}static class Param {private final Map<String, Object> m = new HashMap<>();public <K> K get(String key) {return (K) m.get(key);}}
}

4)HashMap的computeIfAbsent方法,不存在该key则做个操作(再也不会因为漏写 if xx == null出现空指针的bug了) 

// 因此我觉得这个方法是给这个key对应的值一个默认值

   public static ShadowLawPrivilege getPrivilege(Role role, String facilityTag, String privilegeGroupTag, String privilegeIndexTag) {ShadowLawPrivilege shadowLawPrivilege = role.getShadowLawData().getFacilityMap().computeIfAbsent(facilityTag, k -> new ShadowLawFacility()).getPrivilegeGroupMap().computeIfAbsent(privilegeGroupTag, k -> new ShadowLawPrivilegeGroup()).getPrivilegeMap().computeIfAbsent(privilegeIndexTag, k -> new ShadowLawPrivilege());return shadowLawPrivilege;}

5)增强for循环遍历Map // 可以看出很通用,还能遍历数组

// 初始化
Map<Integer, Room> m = Maps.newHashMap(); 
m.put(1, new Room(11));// 遍历
for (Integer key : m.keySet()) {Room r = m.get(key);System.out.println(r);
}

6)Maps.newHashMap(map)其实是浅拷贝,因为从copy中获取1对应的User并修改,old的也被修改了

package org.example.testHashMap;import com.google.common.collect.Maps;
import java.util.Map;
import java.util.Objects;/*** @author jianan* @date 2021/7/8 11:58:51*/
public class TestHashMap {public static void main(String[] args) {Map<Integer, User> old = Maps.newHashMap();old.put(1, new User("a"));// 修改copy中的值Map<Integer, User> copy = Maps.newHashMap(old);User user = copy.get(1);user.setName("250");System.out.println(old);}private static class User {private String name;public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof User)) return false;User user = (User) o;return Objects.equals(getName(), user.getName());}@Overridepublic int hashCode() {return Objects.hash(getName());}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +'}';}}
}/*
{1=User{name='250'}}*/

7)HashMap作为多返回值(还是Model好,字符串容易写错)

// 其实用Pair和Triple更合适 或者 自定义的Vo,避免使用json这种结构

package org.example;import java.util.HashMap;
import java.util.Map;/*** @author jianan* @date 2021/7/2 11:22:29*/
public class TestObject {public static void main(String[] args) {Map<String, Object> map = getResult();int num = (int) map.get("num");String str = (String) map.get("str");System.out.println(num + ":" + str);}public static Map<String, Object> getResult() {Map<String, Object> map = Maps.newHashMap();map.put("num", 1);map.put("str", "aaa");return map;}
}/** 1:aaa*/

8) LinkedHashMap是根据插入的顺序有序是一致的,HashMap无序

package org.example;import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;/*** @author jianan* @date 2021/6/24 17:37:59*/
public class TestLinkedHashMap {public static void main(String[] args) {LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put("c", 1);linkedHashMap.put("a", 3);linkedHashMap.put("b", 2);linkedHashMap.put("d", 4);// 和插入顺序保持一致System.out.println(linkedHashMap);Map<String, Integer> map = new HashMap<>();map.put("c", 1);map.put("a", 3);map.put("b", 2);map.put("d", 4);// 是乱序的System.out.println(map);}
}/*
{c=1, a=3, b=2, d=4}
{a=3, b=2, c=1, d=4}*/

9)removeIf

1.removeIf之 满足某个条件,则移除指定的key

2.使用场景是匹配队列中满4人开赛)  // 如:每一个匹配队列是一个RoomItem

package org.example.testremoveif;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class Main {public static void main(String[] args) {Map<Integer, String> map = new ConcurrentHashMap<>();map.put(1, "1");map.put(2, "2");map.put(55, "55");map.put(3, "3");map.put(4, "4");ScheduledExecutorService schedule = Executors.newScheduledThreadPool(5);schedule.scheduleAtFixedRate(() -> {// 满足条件,则移除map.entrySet().removeIf(entry -> {Integer key = entry.getKey();String value = entry.getValue();if (key < 4) {System.out.println("移除key=" + key + " value=" + value + "剩余:" + map.size() + "  " + Thread.currentThread().getName());return true;}System.out.println(key + " value=" + value + "剩余:" + map.size() + "  " + Thread.currentThread().getName());return false;});}, 1, 1, TimeUnit.SECONDS);}
}/*
移除key=1 value=1剩余:5  pool-1-thread-1
移除key=2 value=2剩余:4  pool-1-thread-1
移除key=3 value=3剩余:3  pool-1-thread-1
4 value=4剩余:2  pool-1-thread-1
55 value=55剩余:2  pool-1-thread-1
4 value=4剩余:2  pool-1-thread-1
55 value=55剩余:2  pool-1-thread-1
4 value=4剩余:2  pool-1-thread-2*/

10)只读的HashMap

// 比如:表数据。虽然是Map,但是取出来values后得到的Collection<Xx>其实基本上是有序的。

package org.example.basic;import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;import java.util.Map;public class TestReadOnlyList {public static void main(String[] args) {// 原始配置数据Map<String, Integer> map = Maps.newHashMap();map.put("1", 111);// 转化为只读mapImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();builder.putAll(map);// 最终只读的mapImmutableMap<String, Integer> itemMap = builder.build();System.out.println(itemMap.get("1"));itemMap.putIfAbsent("2", 22);}
}/*
111
Exception in thread "main" java.lang.UnsupportedOperationExceptionat com.google.common.collect.ImmutableMap.put(ImmutableMap.java:326)at java.base/java.util.Map.putIfAbsent(Map.java:775)at org.example.basic.TestReadOnlyList.main(TestReadOnlyList.java:22)*/

11)newIdentityHashMap // 可重复键值对

package org.example.basic;import com.google.common.collect.Maps;import java.util.Map;public class TestReadOnlyList {public static void main(String[] args) {Map<Integer, Integer> map = Maps.newIdentityHashMap();map.put(128, 1);map.put(128, 1);map.put(2, 3);System.out.println(map);}
}/*
{128=1, 128=1, 2=3}*/

12)putIfabsent

看名字就可以看出,不存在时插入,并且返回值是空。

存在的话,就会返回之前的值,也就是说:不会出现覆盖的情况。

    static {Map<Integer, EBuffAttributeType> map = new HashMap<>();for (EBuffAttributeType type : values()) {if (map.putIfAbsent(type.attributeType, type) != null) {log.error("重复的attributeType={}", type.attributeType);}}typeMap = map;}

这篇关于[HashMap] 1.merge 2.compute 3.包装类小坑 4.computeIfAbsent 5.LinkedHashMap 6.removeIf 7.ImmutableMap 8.的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/856047

相关文章

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

2409wtl,网浏包装

原文 介绍 本教程帮助你用IE引擎构建一个基于WTL,并使用我编写的处理IWebBrowser2接口包装类的迷你浏览器. 因为知道代码可能很难读,因此本教程帮助你逐步开发一个迷你浏览器. 背景 大部分项都与互联网浏览有关.我常用超文本视图使用SDI. 有时,我要用真正的浏览器函数,因此我为IWebBrowser2编写了一个包装器. 此包装类可处理在IE中嵌入的窗口.它还可非常简单的处

Nn criterions don’t compute the gradient w.r.t. targets error「pytorch」 (debug笔记)

Nn criterions don’t compute the gradient w.r.t. targets error「pytorch」 ##一、 缘由及解决方法 把这个pytorch-ddpg|github搬到jupyter notebook上运行时,出现错误Nn criterions don’t compute the gradient w.r.t. targets error。注:我用

HashMap中常用的函数

假设如下HashMap<String, Integer> map = new HashMap<>();获取value值1、返回key为a的valueget(a)2、返回key为a的value,若没有该key返回0getOrDefault(a,0)新增键值对1、新增键值对(a,1)put(a,1)2、如果key为a的键不存在,则存入键值对(a,1)putIfAbsent(a,1)3

hashmap的存值,各种遍历方法

package com.jefflee;import java.util.HashMap;import java.util.Iterator;import java.util.Map;public class HashmapTest {// 遍历Hashmap的四种方法public static void main(String[] args) {//hashmap可以存一个null,把

56. Merge Interval

题目: 解答: 常规的合并,根据前后interval是否有交集判定。 代码: /*** Definition for an interval.* struct Interval {* int start;* int end;* Interval() : start(0), end(0) {}* Interval(int s, int e) : start

C++11,可变参数模板,lambda表达式,包装器

可变参数模板 在C++11中模板也可以接收多个不定参数,就和int printf(const char *format, ...);函数一般模板也可以接收多个参数; // 可变参数模板template<class ...Args>void testArgs(Args... args){}int main(){testArgs(123, 'a', "abc",

容器第五课,Map和HashMap的基本用法,hashMap和HashTable的区别

Map接口 实现Map接口的类用来存储键(Key) --- 值(value)对。 Map接口的实现类有HashMap和TreeMap类 Map类中存储的键---值对通过键来标识,所以键值不能重复 package com.pkushutong.Collection;import java.util.HashMap;import java.util.Map;/*** 测试Map的基本用法

面试:HashMap

文章引用: http://www.importnew.com/7099.html https://blog.csdn.net/niuwei22007/article/details/52005329 HashMap的工作原理是近年来常见的Java面试题。几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么

HashMap 源码分析(删除+总结)JDK1.8

文章来源: 1 https://segmentfault.com/a/1190000012926722#articleHeader7 2 https://www.zhihu.com/question/20733617 3 https://tech.meituan.com/java-hashmap.html 4 https://www.zhihu.com/question/5752