HashMap源码解析(2)

来源:互联网 发布:国家数据统计局官网 编辑:程序博客网 时间:2024/06/05 10:02

    万里长征,翻译完HashMap注释居然花了一周时间。看来解析源码也要好久,先把源码copy过来咯


   HashMap继承AbstractMap,实现了接口:Map<K, V>, Cloneable, Serializable。

public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable{    /**     * The default initial capacity - MUST be a power of two. 默认初始容量,值必须是2的幂。     */    static final int DEFAULT_INITIAL_CAPACITY = 16;    /**     * The maximum capacity, used if a higher value is implicitly specified     * by either of the constructors with arguments.     * MUST be a power of two <= 1<<30.  最大容量,初始值时2^30     */    static final int MAXIMUM_CAPACITY = 1 << 30;    /**     * The load factor used when none specified in constructor. 默认加载因子,默认值为0.75     */    static final float DEFAULT_LOAD_FACTOR = 0.75f;    /**     * The table, resized as necessary. Length MUST Always be a power of two.Entry数组,大小必须为2的幂。     */    transient Entry<K,V>[] table;    /**     * The number of key-value mappings contained in this map.已存元素的个数,     */    transient int size;    /**     * The next size value at which to resize (capacity * load factor). 阈值,当size>=threshold就会扩容     * @serial     */    int threshold;    /**     * The load factor for the hash table.加载因子     *     * @serial     */    final float loadFactor;    /**     * The number of times this HashMap has been structurally modified     * Structural modifications are those that change the number of mappings in     * the HashMap or otherwise modify its internal structure (e.g.,     * rehash).  This field is used to make iterators on Collection-views of     * the HashMap fail-fast.  (See ConcurrentModificationException).hashmap结构性修改的次数,     结构性修改是指改变映射对的数量或内部结构的修改。这个变量是为了辅助hashmap快速修改机制。
     */
transient int modCount;
     */


此时我们介绍下构造函数,转自(http://blog.csdn.net/ghsau/article/details/16890151)HashMap一共重载了4个构造方法,分别为:构造方法摘要HashMap()           构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMapHashMap(int initialCapacity)           构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMapHashMap(int initialCapacity, float loadFactor)           构造一个带指定初始容量和加载因子的空 HashMapHashMap(Map<? extendsK,? extendsV> m)           构造一个映射关系与指定 Map 相同的 HashMap
我们看下第三个构造方法,如下源码所示其他构造方法都是引用的这个构造方法。
    /**     * Constructs an empty <tt>HashMap</tt> with the specified initial     * capacity and load factor.     *     * @param  initialCapacity the initial capacity     * @param  loadFactor      the load factor     * @throws IllegalArgumentException if the initial capacity is negative     *         or the load factor is nonpositive     */    public HashMap(int initialCapacity, float loadFactor) {        if (initialCapacity < 0)//参数合规性检查            throw new IllegalArgumentException("Illegal initial capacity: " +                                               initialCapacity);        if (initialCapacity > MAXIMUM_CAPACITY)            initialCapacity = MAXIMUM_CAPACITY;        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal load factor: " +                                               loadFactor);        // Find a power of 2 >= initialCapacity        int capacity = 1;//容量设置为2的幂        while (capacity < initialCapacity)            capacity <<= 1;        //设置加载因子        this.loadFactor = loadFactor;        threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);        table = new Entry[capacity];//初始化hash表        useAltHashing = sun.misc.VM.isBooted() &&                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);        init();    }    /**     * Constructs an empty <tt>HashMap</tt> with the specified initial     * capacity and the default load factor (0.75).     *     * @param  initialCapacity the initial capacity.     * @throws IllegalArgumentException if the initial capacity is negative.     */    public HashMap(int initialCapacity) {        this(initialCapacity, DEFAULT_LOAD_FACTOR);    }    /**     * Constructs an empty <tt>HashMap</tt> with the default initial capacity     * (16) and the default load factor (0.75).     */    public HashMap() {        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);    }    /**     * Constructs a new <tt>HashMap</tt> with the same mappings as the     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with     * default load factor (0.75) and an initial capacity sufficient to     * hold the mappings in the specified <tt>Map</tt>.     *     * @param   m the map whose mappings are to be placed in this map     * @throws  NullPointerException if the specified map is null     */    public HashMap(Map<? extends K, ? extends V> m) {        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,                      DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);        putAllForCreate(m);    }    // internal utilities    /**     * Initialization hook for subclasses. This method is called     * in all constructors and pseudo-constructors (clone, readObject)     * after HashMap has been initialized but before any entries have     * been inserted.  (In the absence of this method, readObject would     * require explicit knowledge of subclasses.)     */    void init() {    }    /**     * Retrieve object hash code and applies a supplemental hash function to the     * result hash, which defends against poor quality hash functions.  This is     * critical because HashMap uses power-of-two length hash tables, that     * otherwise encounter collisions for hashCodes that do not differ     * in lower bits. Note: Null keys always map to hash 0, thus index 0.     */    final int hash(Object k) {        int h = 0;        if (useAltHashing) {            if (k instanceof String) {                return sun.misc.Hashing.stringHash32((String) k);            }            h = hashSeed;        }        h ^= k.hashCode();        // This function ensures that hashCodes that differ only by        // constant multiples at each bit position have a bounded        // number of collisions (approximately 8 at default load factor).        h ^= (h >>> 20) ^ (h >>> 12);        return h ^ (h >>> 7) ^ (h >>> 4);    }
HashMap put方法,允许加入key value 为null。 
public V put(K key, V value) {      // 处理key为null,HashMap允许key和value为null      if (key == null)          return putForNullKey(value);      // 得到key的哈希码      int hash = hash(key);      // 通过哈希码计算出bucketIndex      int i = indexFor(hash, table.length);      // 取出bucketIndex位置上的元素,并循环单链表,判断key是否已存在      for (Entry<K,V> e = table[i]; e != null; e = e.next) {          Object k;          // 哈希码相同并且对象相同时          if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {              // 新值替换旧值,并返回旧值              V oldValue = e.value;              e.value = value;              e.recordAccess(this);              return oldValue;          }      }        // key不存在时,加入新元素      modCount++;      addEntry(hash, key, value, i);      return null;  }  
    void addEntry(int hash, K key, V value, int bucketIndex) {        if ((size >= threshold) && (null != table[bucketIndex])) {//判断是否需要扩容            resize(2 * table.length);//resize函数所做的就是将旧table rehash到新的newtable            hash = (null != key) ? hash(key) : 0;            bucketIndex = indexFor(hash, table.length);        }        createEntry(hash, key, value, bucketIndex);    }    /**     * Like addEntry except that this version is used when creating entries     * as part of Map construction or "pseudo-construction" (cloning,     * deserialization).  This version needn't worry about resizing the table.     *     * Subclass overrides this to alter the behavior of HashMap(Map),     * clone, and readObject.     */    void createEntry(int hash, K key, V value, int bucketIndex) {        Entry<K,V> e = table[bucketIndex];        table[bucketIndex] = new Entry<>(hash, key, value, e);        size++;    }
最后标记下内部类,Entry
static class Entry<K,V> implements Map.Entry<K,V> {    final K key;    V value;    Entry<K,V> next;    int hash;    /**     * Creates new entry.     */    Entry(int h, K k, V v, Entry<K,V> n) {        value = v;        next = n;        key = k;        hash = h;    }    public final K getKey() {        return key;    }    public final V getValue() {        return value;    }    public final V setValue(V newValue) {        V oldValue = value;        value = newValue;        return oldValue;    }    public final boolean equals(Object o) {        if (!(o instanceof Map.Entry))            return false;        Map.Entry e = (Map.Entry)o;        Object k1 = getKey();        Object k2 = e.getKey();        if (k1 == k2 || (k1 != null && k1.equals(k2))) {            Object v1 = getValue();            Object v2 = e.getValue();            if (v1 == v2 || (v1 != null && v1.equals(v2)))                return true;        }        return false;    }    public final int hashCode() {        return (key==null   ? 0 : key.hashCode()) ^               (value==null ? 0 : value.hashCode());    }    public final String toString() {        return getKey() + "=" + getValue();    }    /**     * This method is invoked whenever the value in an entry is     * overwritten by an invocation of put(k,v) for a key k that's already     * in the HashMap.     */    void recordAccess(HashMap<K,V> m) {    }    /**     * This method is invoked whenever the entry is     * removed from the table.     */    void recordRemoval(HashMap<K,V> m) {    }}

 
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 拉大便的时候滴血 大便出血鲜红色 拉的屎有血 解大便有血 擦屁纸上有血 小孩大便带血 肛门血 大便干结带血 大便里面有血 大便隐血是什么意思 男人拉血是啥原因 大便拉稀出血 大便手纸擦后有血迹 早上大便有血 大便血鲜红 大便出好多血 人拉血是怎么回事 拉血原因 拉稀有血 大便出血 鲜红 肛出血是怎么回事 大便潜血检查 拉屎带血 大便出血痛 儿童大便带血 大便流血是什么病症 屎中带血 拉肚子有血是什么原因 大便出鲜血怎么调理 肛门带血 为什么会突然便血 便衣支队 便衣 敌后便衣队 便衣边江 敌后便衣队传奇 敌后便衣队传奇演员表 便装 商务便装 男士便装 男便装