Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
Map
实现分为通用,专用和并发实现。
三个通用 Map
实现是 HashMap
,TreeMap
和 LinkedHashMap
。如果需要 SortedMap
操作或以键排序的 Collection
-视图迭代,请使用 TreeMap
;如果你想要最大速度而不关心迭代顺序,请使用 HashMap
;如果你想要近似 HashMap
性能和插入顺序迭代,请使用 LinkedHashMap
。在这方面,Map
的情况类似于 Set
。同样,Set Implementations 部分中的所有其他内容也适用于 Map
实现。
LinkedHashMap
提供了 LinkedHashSet
不具备的两项功能。创建 LinkedHashMap
时,可以基于 key 的访问而不是插入顺序来对其进行排序。换句话说,仅查找与键相关联的值会将该键带到 map 的末尾。此外,LinkedHashMap
提供了 removeEldestEntry
方法,可以重写该方法,以便在将新映射添加到 map 时自动移除过时映射的策略。这使得实现自定义缓存变得非常容易。
例如,此覆盖将允许 map 多达 100 个条目,然后每次添加新条目时它将删除最旧条目,从而保持 100 个条目的稳定状态。
private static final int MAX_ENTRIES = 100; protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_ENTRIES; }
有三个专用 Map 实现 EnumMap
,WeakHashMap
和 IdentityHashMap
。EnumMap
,内部实现为 array
,是一个与枚举键一起使用的高性能 Map
实现。此实现将 Map
接口的丰富性和安全性与接近数组的速度相结合。如果要将枚举映射到值,则应始终使用 EnumMap
而不是数组。
WeakHashMap
是 Map
接口的一个实现,它只存储对其键的弱引用。仅存储弱引用允许在其键不再在 WeakHashMap
之外引用时对其进行垃圾回收。此类提供了利用弱引用功能的最简单方法。它对于实现“类似注册表”的数据结构很有用,其中当任何线程不再可以访问其键时,条目的实用程序就会消失。
IdentityHashMap
是基于哈希表的基于身份的 Map
实现。此类对于拓扑保留对象图转换非常有用,例如序列化或深度复制。要执行此类转换,你需要维护一个基于身份的“节点表”,以跟踪已经看到的对象。基于身份的 map 还用于维护动态调试器和类似系统中的对象到元信息映射。最后,基于身份的地图有助于阻止故意不正常的 equals
方法导致的“欺骗攻击”,因为 IdentityHashMap
永远不会调用键的 equals
的方法。这种实现的另一个好处是它很快。
java.util.concurrent
包中包含 ConcurrentMap
接口,该接口继承了 Map
原子的 putIfAbsent
,remove
,replace
方法,且 ConcurrentHashMap
实现那个接口。
ConcurrentHashMap
是一个由哈希表支持的高度并发、高性能的实现。执行获取时,此实现永远不会阻塞,并允许客户端选择更新的并发级别。它旨在作为 Hashtable
的替代品:除了实现 ConcurrentMap
之外,它还支持 Hashtable
特有的所有遗留方法。同样,如果你不需要遗留操作,请小心使用 ConcurrentMap
接口对其进行操作。