分类: Java
2012-02-27 11:52:35
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
此接口取代 Dictionary 类,后者完全是一个抽象类,而不是一个接口。
Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序 定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类。
Map |
保存键值对成员,基于键找值操作,使用compareTo或compare方法对键进行排序 |
HashMap |
能满足用户对Map的通用需求 |
键成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 |
TreeMap |
支持对键有序地遍历,使用时建议先用HashMap增加和删除成员,最后从HashMap生成TreeMap; 附加实现了SortedMap接口,支持子Map等要求顺序的操作 |
键成员要求实现Comparable接口,或者使用Comparator构造TreeMap键成员一般为同一类型。 |
||
LinkedHashMap |
保留键的插入顺序,用equals 方法检查键和值的相等性 |
成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 |
再看看排序的Map是如何使用
未排序前HashMap:{0=第 3 个放入的元素:0.46674461834753656
, 34=第 2 个放入的元素:34.54670083072801
, 50=第 9 个放入的元素:50.82172311275165
, 80=第 7 个放入的元素:80.08590191596085
, 37=第 6 个放入的元素:37.810256398638984
, 22=第 5 个放入的元素:22.805908526261852
, 97=第 1 个放入的元素:97.2777359407105
, 92=第 8 个放入的元素:92.23124191087155
, 10=第 0 个放入的元素:10.331082717129602
}
未排序前LinkedHashMap:{10=第 0 个放入的元素:10.331082717129602
, 97=第 1 个放入的元素:97.2777359407105
, 34=第 2 个放入的元素:34.54670083072801
, 0=第 3 个放入的元素:0.46674461834753656
, 22=第 5 个放入的元素:22.805908526261852
, 37=第 6 个放入的元素:37.810256398638984
, 80=第 7 个放入的元素:80.08590191596085
, 92=第 8 个放入的元素:92.23124191087155
, 50=第 9 个放入的元素:50.82172311275165
}
排序后:{0=第 3 个放入的元素:0.46674461834753656
, 10=第 0 个放入的元素:10.331082717129602
, 22=第 5 个放入的元素:22.805908526261852
, 34=第 2 个放入的元素:34.54670083072801
, 37=第 6 个放入的元素:37.810256398638984
, 50=第 9 个放入的元素:50.82172311275165
, 80=第 7 个放入的元素:80.08590191596085
, 92=第 8 个放入的元素:92.23124191087155
, 97=第 1 个放入的元素:97.2777359407105
}
排序后:{0=第 3 个放入的元素:0.46674461834753656
, 10=第 0 个放入的元素:10.331082717129602
, 22=第 5 个放入的元素:22.805908526261852
, 34=第 2 个放入的元素:34.54670083072801
, 37=第 6 个放入的元素:37.810256398638984
, 50=第 9 个放入的元素:50.82172311275165
, 80=第 7 个放入的元素:80.08590191596085
, 92=第 8 个放入的元素:92.23124191087155
, 97=第 1 个放入的元素:97.2777359407105
}
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。迭代 collection 视图所需的时间与 HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。
如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使用足够大的初始容量创建它将使得映射关系能更有效地存储。
public class LinkedHashMap
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入 键,则插入顺序不受影响。(如果在调用 m.put(k, v) 前 m.containsKey(k) 返回了 true,则调用时会将键 k 重新插入到映射 m 中。)
此实现可以让客户避免未指定的、由 (及 )所提供的通常为杂乱无章的排序工作,同时无需增加与 相关的成本。使用它可以生成一个与原来顺序相同的映射副本,而与原映射的实现无关:
void foo(Map m) { Map copy = new LinkedHashMap(m); ... } 如果模块通过输入得到一个映射,复制这个映射,然后返回由此副本确定其顺序的结果,这种情况下这项技术特别有用。(客户通常期望返回的内容与其出现的顺序相同。)提供特殊的来创建链接哈希映射,该哈希映射的迭代顺序就是最后访问其条目的顺序,从近期访问最少到近期访问最多的顺序(访问顺序)。这种映射很适合构建 LRU 缓存。调用 put 或 get 方法将会访问相应的条目(假定调用完成后它还存在)。putAll 方法以指定映射的条目集迭代器提供的键-值映射关系的顺序,为指定映射的每个映射关系生成一个条目访问。任何其他方法均不生成条目访问。特别是,collection 视图上的操作不 影响底层映射的迭代顺序。
可以重写 方法来实施策略,以便在将新映射关系添加到映射时自动移除旧的映射关系。
此类提供所有可选的 Map 操作,并且允许 null 元素。与 HashMap 一样,它可以为基本操作(add、contains 和 remove)提供稳定的性能,假定哈希函数将元素正确分布到桶中。由于增加了维护链接列表的开支,其性能很可能比 HashMap 稍逊一筹,不过这一点例外:LinkedHashMap 的 collection 视图迭代所需时间与映射的大小 成比例。HashMap 迭代时间很可能开支较大,因为它所需要的时间与其容量 成比例。
链接的哈希映射具有两个影响其性能的参数:初始容量和加载因子。它们的定义与 HashMap 极其相似。要注意,为初始容量选择非常高的值对此类的影响比对 HashMap 要小,因为此类的迭代时间不受容量的影响。
public class TreeMap基于红黑树(Red-Black tree)的 实现。该映射根据其键的进行排序,或者根据创建映射时提供的 进行排序,具体取决于使用的构造方法。