HashMap 源码解析(1)

Mark 一下自己开始写总结,以前很大部分是看其他大牛的,然后依葫芦画瓢写写。

研究好几次HashMap,过一段时间就忘。所以决定直接打开源码,从最底层一步步了解。 先从翻译HashMap英文注释开始吧

JDK8 HashMap 注释翻译

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

  Hash table based implementation of the <tt>Map</tt> interface.  This implementation provides all of the optional map operations, and permits  <tt>null</tt> values and the <tt>null</tt> key.  (The <tt>HashMap</tt> class is roughly equivalent to <tt>Hashtable</tt>, except that it is unsynchronized and permits nulls.)  This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.


HashMap是基于Map接口实现的,其实现了Map接口中的所有操作。HashMap允许Value和Key为null(HashMap与HashTable相似,除了HashMap是非同步的也是非线程安全的、同时HashMap允许为空)。HashMap并不保证Map的顺序(即数据存储顺序与put顺序有可能不同),同时并不保证它的是顺序是一程不变的(HashMap rehash时,顺序可能发生改变。)


This implementation provides constant-time performance for the basic operations (<tt>get</tt> and <tt>put</tt>), assuming the hash function disperses the elements properly among the buckets.  Iteration over collection views requires time proportional to the "capacity" of the  <tt>HashMap</tt> instance (the number of buckets) plus its size (the number of key-value mappings).  Thus, it's very important not to set the initial  capacity too high (or the load factor too low) if iteration performance is important.


HashMap 基本操作(get,put)是常量级的。假设hash函数能够将元素均匀的分布在每个桶(HashMap有一个叫做Entry的内部类,它用来存储key-value对。上面的Entry对象是存储在一个叫做table的Entry数组中。table的索引在逻辑上叫做“桶”(bucket),它存储了链表的第一个元素。)中。那么HashMap的遍历的时间取决于它的容量(capacity,桶的数量)和它的Size(Key-Value映射数量)。如果对性能要求较高的话,初始的capacity不能设置太高,加载因子(loadFactor)也不能太低(过低会造成空桶数量较多),当然加载因子过高也不可以(会发生碰撞,可能导致某个桶后面有很多元素)。


  An instance of <tt>HashMap</tt> has two parameters that affect its performance: <i>initial capacity</i> and <i>load factor</i>.  The  <i>capacity</i> is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created.  The <i>load factor</i> is a measure of how full the hash table is allowed to get before its capacity is automatically increased.  When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is <i>rehashed</i> (that is, internal data structures are rebuilt) so that the hash table has approximately twice the  number of buckets.


HashMap的性能受两个参数的影响:初始容量(initialCapacity)、加载因子(loadFactor)。容量是指hash表中桶的数量,初始容量是指hash表创建时容量的初始化值。加载因子是衡量hash表满的程度,当hash表中Entry的数量超过 加载因子与容量的乘积时,则HashMap的容量自动增加2倍,增加是hash表会rehash,内部数据结构会重新构建。


  As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs.  Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the <tt>HashMap</tt> class, including <tt>get</tt> and <tt>put</tt>).  The expected number of entries in  the map and its load factor should be taken into account when  setting its initial capacity, so as to minimize the number of  rehash operations.  If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash  operations will ever occur.


通常来讲,加载因子默认值为0.75,加载因子大的话会降低空间开销,但是查找开销增大(HashMap多数操作中,如get,put)。当设置初始容量时,应考虑放进map中entry的数量和加载因子,以降低rehash的操作次数(rehash较大的影响HashMap性能)。如果初始容量与加载因子的乘积大于预计放进map的entry数量,那么永远不需要rehash。


  If many mappings are to be stored in a <tt>HashMap</tt> instance, creating it with a sufficiently large capacity will allow  the mappings to be stored more efficiently than letting it perform automatic rehashing as needed to grow the table.  Note that using many keys with the same {@code hashCode()} is a sure way to slow down performance of any hash table. To ameliorate impact, when keys  are {@link Comparable}, this class may use comparison order among keys to help break ties.


如果HashMap中有很多K-V映射,那么在创建实例时就设置足够大的容量,这样避免自动扩容rehash降低性能的影响。需要注意的是许多key可能有相同的hashCode(),这会导致hash表的性能下降,为避免这种情况,Key可以实现Comparable接口,这样类就可以比较Key。


  <strong>Note that this implementation is not synchronized.</strong> If multiple threads access a hash map concurrently, and at least one of  the threads modifies the map structurally, it <i>must</i> be synchronized externally.  (A structural modification is any operation  that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)  This is typically accomplished by synchronizing on some object that naturally encapsulates the map.

注意HashMap是非同步的。如果多个线程同时访问一个hashmap,且至少有一个线程对map的结构会进行修改,那么必须在外部加上同步。(结构的修改指,任何添加或删除一个或多个KV映射,但是修改已有的KV映射的值不属于结构修改。)在外部加同步,可以使用synchronized(Map)实现map同步。


   If no such object exists, the map should be "wrapped" using the {@link Collections#synchronizedMap Collections.synchronizedMap} method.  This is best done at creation time, to prevent accidental unsynchronized access to the map:<pre> Map m = Collections.synchronizedMap(new HashMap(...));</pre>


可以通过Map m = Collections.synchronizedMap(new HashMap(...));来创建同步的HashMap(1.8有currentHashMap,后面计划研究)


The iterators returned by all of this class's "collection view methods" are <i>fail-fast</i>: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own  <tt>remove</tt> method, the iterator will throw a {@link ConcurrentModificationException}.  Thus, in the face of  concurrent  modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.


当迭代器创建后,只有通过迭代器的remove方法可以对hashmap进行结构性的修改,其他任何对HashMap结构性修改的操作,都会引起迭代器抛出并发修改错误(ConcurrentModificationExcelption 继承 RuntimeException).当面对并发修改错误时,迭代器会快速明了的报错,而不是冒险在以后不确定的时间抛出。


Note that the fail-fast behavior of an iterator cannot be guaranteed  as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification.  Fail-fast iterators  throw <tt>ConcurrentModificationException</tt> on a best-effort basis.  Therefore, it would be wrong to write a program that depended on this  exception for its correctness: <i>the fail-fast behavior of iterators should be used only to detect bugs.


需要注意的是,迭代器的快速失败行为并不能得到保证,一般来说,存在非同步并发修改时,并不能做出十分准备的保证。快速失败迭代器会尽最大努力抛出同步修改错误。因此我们不能依赖此异常编程,而是仅用于检测程序错误。
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 *
 * @author  Doug Lea
 * @author  Josh Bloch
 * @author  Arthur van Hoff
 * @author  Neal Gafter
 * @see     Object#hashCode()
 * @see     Collection
 * @see     Map
 * @see     TreeMap
 * @see     Hashtable
 * @since   1.2
 */

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值