目录
1 背景
工作学习中经常用到的HashMap,里面知识点很多,此博客从源码角度出发详细分析一下。本文源码取自JDK8。
2 类注释
/**
* 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.
不支持线程同步;key和value可以为null;不保证顺序性。
问:为什么HashTable和ConcurrentHashMap不支持null?
答:hashTable和concurrentHashMap不允许null的键,因为无法分辨是key没找到的null还是有key值为null,这在多线程里面是模糊不清的,所以压根就不让put null。hashMap是非多线程工具类,可以通过map.contains(key)来区分这种情况。
* <p>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.
在hash函数合理的前提下,get和put操作复杂度是常数O(1)。如果对迭代操作的性能要求比较高的话,注意不能将初始容量设置的太高也不能把负载因子设置的过低。
* <p>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.
Entry个数达到load factor * capacity,发生rehash,扩容成之前的两倍。
问:为什么按照两倍扩容?
答:1、减少hash碰撞 2、方便转换成位运算
* <p>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.
通常,默认负载因子(.75)在时间和空间成本之间提供了一个很好的折衷方案。 较高的值会减少空间开销,但会增加查找成本(在HashMap类的大多数操作中都得到体现,包括get和put)。 设置映射表的初始容量时,应考虑映射中的预期条目数及其负载因子,以最大程度地减少重新哈希操作的数量。 如果初始容量大于最大条目数除以负载因子,则将不会进行任何哈希操作。