本文主要是介绍[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.的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!