翻译来源 java.util.HashMap JDK1.7
HashMap API 所有翻译,请查看翻译目录。
简介
HashMap
是基于哈希表的Map
接口的实现。该实现提供了所有可选的map操作,并允许key
和value
为null
。HashMap
大致等价于Hashtable
(is roughly equivalent to),不同之处在于HashMap
是非同步的,并且允许key
和value
为null
。该类不保证(makes no guarantees as to)map的顺序;需要特别指出的是(in particular),它不保证顺序随时间保持不变(remain constant over time)。
译者按
不保证map的顺序:不保证元素实际存储的顺序与执行put操作的顺序一致
不保证顺序随时保持不变:扩容时会变
假设散列函数正确地分散了桶间的元素,该实现为**get
和put
基本操作提供常量级时间性能(constant-time performance)。对集合视图进行迭代操作**(Iteration over collection views)所需的时间,与HashMap
实例的容量(桶数)及其大小(键值对数)成比例(proportional to)。因此,如果对迭代性能要求比较高的话,初始容量不要设置的过高,或者装载因子不要设置过低。
译者按:
散列函数正确地分散了桶间的元素:为一个数据类型实现一个优秀的散列方法需要满足三个条件:一致性,等价的键必然产生相等的散列值;高效性,计算快速简便;均匀性,均匀地散列所有的键。(语出红皮《算法》第4版)
一个HashMap
实例有两个影响自身性能的参数:初始容量(initial capacity
)和装载因子(load factor
)。容量是哈希表中桶的数量,初始容量只是创建哈希表时的容量。装载因子是哈希表在容量自动增加之前允许获取多满的一个度量(a measure of)。当哈希表中表项(entry)的数量超过(exceed)装载因子与当前容量的乘积时,哈希表就会rehash
,也就是内部数据结构重构,导致哈希表桶数大约(approximately)翻倍。
作为一般规则(As a general rule),默认装载因子(0.75)在时间和空间成本之间提供了很好的折中(offers a good tradeoff between)。更高的值减少了空间开销(decrease the space overhead),但增加了查找成本(increase the lookup cost),这反映在HashMap
类的大部分操作上,包括get
和put
。当设定map的初始容量时,map中表项的预期数量和map的装载因子应被考虑在内(be taken into account),以便使rehash
操作次数最小。如果初始容量大于最大条目数除以装载因子,rehash
操作将永远不会发生。
如果要往一个HashMap
实例中存放很多映射,在创建该实例时,就给它一个用于存放映射的足够大的容量(a sufficiently large capacity),要比在需要扩容表时才让它自动执行rehash
,更有效率(more efficiently than)。
注意,HashMap
是非同步的。如果多个线程并发地(concurrently)访问一个HashMap
,并且至少有一个线程结构化地修改该map,那么必须在外部同步。(所谓结构化修改是指,添加或删除一个或多个映射的任何操作,仅仅(merely)改变与一个map实例中已经包含的键相关联的值不是一个结构性修改)。理所当然地,这通常是通过在封装了该map的某个对象上进行同步来实现的(is typically accomplished by)。如果不存在这样的对象,应该使用Collections.synchronizedMap
方法来封装该map。为了防止对该map进行偶然地异步访问(prevent accidental unsynchronized access),最好在创建的时候就这么干:
Map m = Collections.synchronizedMap(new HashMap(…));
该类的所有“集合视图方法”返回的迭代器都有fail-fast
机制:在该迭代器被创建之后的任何时刻,如果该map被结构化地修改,除了通过迭代器自身的remove
方法修改之外,不论以何种方式修改,该迭代器都将抛出一个并发修改异常ConcurrentModificationException
。因此,在面临并发修改时,迭代器会快速明了地失败,这远比冒着随便在未来一个不确定时间的不确定行为的风险要好。
注意,一个迭代器的快速失败行为无法被保证,一般来说,在存在非同步的并发修改时(in the presence of),不可能作出任何绝对的保证(make any hard guarantees)。快速失败迭代器尽最大努力(on a best-effort basis)抛出 ConcurrentModificationException
。因此,编写依赖于此异常的程序的做法是错误的,正确做法是(for its correctness):迭代器的快速失败行为应该仅用于检测程序错误。
该类是Java集合框架的一个成员。