Map家族
1、顶层接口:Map<K,V>
- 实现:定义了 键值对的存储 的抽象接口
- 常用方法:put() get() remove() containsKey() entrySet() keySet() values()
- 底层:只是规范,并不关心具体数据结构
- 应用:统一API,让不同实现类有相同的使用方式
- 作用:抽象层,解耦调用方与实现类
2、HashMap
-
底层:
- jdk 1.7:数组+链表 jdk1.8+:数组+链表+红黑树(后链表长度 > 8 时转为红黑树)
- 哈希函数:对hashCode做扰动运算,减少冲突
- 扩容:容量翻倍,重新hash
-
应用:缓存、统计、配置存储
-
作用:O(1)平均查找、插入效率 无序查找,效率优先
-
业务场景(最常用的):
- 缓存:存储一些临时数据,比如一个用户的ID和用户信息的映射
Map<Integer, User> userCache = new HashMap(); userCache.put(1001, new User("wjj"));- 快速查找:比如统计单词出现的次数
Map<String, Integer> countMap = HashMap<>(); // 统计 apple 出现的次数,出现就+1,否则放入1- 配置存储:存储一些配置项,比如数据库连接参数(key=配置名,value=值)
3、LinkedHashMap
-
底层:继承HashMap,多了一个 双向链表,保证插入顺序或访问顺序
-
特点:有序(插入顺序 或 LRU顺序)
-
业务场景:
- LRU缓存(最常见):可以设置accessOrder = true ,自动把最近访问的放到最后,淘汰最久没有访问的 (accessOrder 按照访问顺序排列 false就是按照插入顺序)
LinkedHashMap<Integer, String> lruCache = new LinkedHashMap<>(16, 0.75f, true); // 第一个参数:初始容量 第二个:负载因子(当元素超过16*0.75=12时进行扩容) // 第三个参数:是否按照访问顺序排序- 需要顺序输出的情况:比如保存菜单项,按用户定义的顺序展示
4、TreeMap
-
底层:红黑树(有序二叉查找树)
-
特点:按照 key 排序(自然排序 or Comparator)。查找 / 插入O(logN)
-
业务场景:
- 排行榜:比如存储用户分数,key = 分数,value = 用户,天然排序
TreeMap<Integer, String> rank = new TreeMap<>(); rank.put(100, "wjj"); rank.put(200, "jjw"); // TreeMap会自动进行排序- 范围查询:比如找“分数在80-100的所有学生”
SortedMap<Integer, String> sub = rank.subMap(80, 101); /* TreeMap就是实现了SortedMap接口的具体实现类 SortedMap是一个接口,规定 有序Map 应该支持的一些功能 1. subMap(fromKey, toKey) 获取某个范围的子视图 2. headMap(toKey) 获取比某个key小的所有映射 3. tailMap() 获取比某个key大的所有映射 4. firstKey()、lastKey() 获取最大、最小key */
5、ConcurrentHashMap
为什么使用这个?
- HashMap线程不安全,多线程环境下会出现问题(eg:死循环、数据丢失)
- Hashtable虽然线程安全,但是因为对方加了全表锁(synchronized),并发性能很差
-
底层:分段锁(jdk7),CAS+synchronized(jdk8)
-
特点:高并发环境下使用,性能远高于Hashtable,其迭代器是弱一致性,其他线程更改Map,不会抛异常
-
业务场景:
- 并发缓存:多线程同时读写缓存数据(用户session、token、临时数据啥的)
ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>(); cache.put("token", "xyz123");- 统计并发管理访问量:比如电商系统中统计商品的访问次数
- 存放共享资源:比如多个线程共享的用户session信息
6、Hashteble
- 底层:数组+链表
- 特点:线程安全(方法上加synchronized,全),不允许null key和null value
- 业务场景:
- 早期多线程程序:现在基本被ConcurrentHashMap替代
- 维护老项目会遇到,新开发基本用不上
7、WeakHashMap
- 底层:key用弱引用存储,GC发现key没有强引用时,会自动回收对应的entry
- 特点:适合做“临时性缓存”
- 业务场景:
- 缓存场景:避免缓存导致内存泄露,比如class loader缓存(当key没人引用时,GC会自动清理)
- 图片缓存:android中用过,用于图片对象的缓存
8、IdentityHashMap
-
底层:和HashMap类似,但key比较用 ==(地址比较) 而不是equals()
-
业务场景:
- 对象唯一性映射:比如序列化时,判断一个对象是否已经被处理过
// 普通 HashMap 会认为两个内容一样的对象是同一个,但 IdentityHashMap 可以区分 String a = new String("abc"); String b = new String("abc"); Map<String, String> map = new IndentityHashMap<>(); map.put(a, "A"); map.put(b, "B"); System.out.println(map.size()) // 输出2 而 HashMap 会输出 1- 特殊框架实现:一般业务开发几乎不用