zoukankan      html  css  js  c++  java
  • HashMap

      HashMap的底层主要是基于数组+链表来实现的,根据HashCode可以很快的查询到对象所存储的位置。例如:

      

    导入包:

    package java.util;
    import java.io.*;

    成员变量:

    public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable {
    //默认的初始化容量大小,必须是2的幂(计算hash值和索引的时候效率更高) static final int DEFAULT_INITIAL_CAPACITY = 16;
    //最大的容量,必须是2的幂,且小于 1<<30. static final int MAXIMUM_CAPACITY = 1 << 30;
    //默认的负载因子 static final float DEFAULT_LOAD_FACTOR = 0.75f;
    //存放Entry的表,长度可以调整。长度必须始终是2的幂。 transient Entry[] table;
    //map中键值对的数量,而不是table的length transient int size;
    //阈值,扩容的临界值 value = (capacity * load factor). int threshold;
    //负载因子 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). 用volatile修饰的,表的修改次数,用于确保在迭代iterators的时候,表没有被修改 */ transient volatile int modCount; .... }

     内部类Entry<K, V>:

    static class Entry<K, V> implements Map.Entry<K, V> {
        final K key;
        V value;
        Entry<K, V> next;
        final 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;
        }
        //比较对象是否相等,需要比较key和value
        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;
        }
        //hash值得计算
        public final int hashCode() {
            return (key==null? 0:key.hashCode()) ^ (value==null? 0:value.hashCode());//异或值,两边不同才是1.
        }
        
        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){}
      
      //recordAccess、recordRemoval两个方法,用于子类实现的,参考LinkedHashMap
      /** 
         * This method is invoked by the superclass whenever the value 
         * of a pre-existing entry is read by Map.get or modified by Map.set. 
         * If the enclosing Map is access-ordered, it moves the entry 
         * to the end of the list; otherwise, it does nothing. 
         */ 
        void recordAccess(HashMap<K,V> m) { 
            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; 
            if (lm.accessOrder) { 
                lm.modCount++; 
                remove(); 
                addBefore(lm.header); 
            } 
        } 
    
        void recordRemoval(HashMap<K,V> m) { 
            remove(); 
        } 
      这两个方法是有用的 用于实现LRU     
    }

     内部类HashIterator迭代器:

    private abstract class HashIterator<E> implements Iterator<E> {
        
        Entry<K,V> next;    // next entry to return
        int expectedModCount;    // For fast-fail,确保HashMap在迭代中没有被修改
        int index;        // current slot
        Entry<K,V> current;    // current entry
    
        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }
    
        public final boolean hasNext() {
            return next != null;
        }
    
        final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();
    
            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
            current = e;
            return e;
        }
    
        public void remove() {
            if (current == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Object k = current.key;
            current = null;
            HashMap.this.removeEntryForKey(k);
            expectedModCount = modCount;
        }
    }

     内部类ValueIterator、KeyIterator、EntryIterator迭代器:

    private final class ValueIterator extends HashIterator<V> {
        public V next() {
            return nextEntry().value;
        }
    }
    
    private final class KeyIterator extends HashIterator<K> {
        public K next() {
            return nextEntry().getKey();
        }
    }
    
    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
        public Map.Entry<K,V> next() {
            return nextEntry();
        }
    }
    
    // Subclass overrides these to alter behavior of views' iterator() method
    Iterator<K> newKeyIterator()   {
        return new KeyIterator();
    }
    Iterator<V> newValueIterator()   {
        return new ValueIterator();
    }
    Iterator<Map.Entry<K,V>> newEntryIterator()   {
        return new EntryIterator();
    }

     视图Views,Key、Value、Entry:

    //Views 视图
    private transient Set<Map.Entry<K,V>> entrySet = null;
    /**
     * Returns a {@link Set} view of the keys contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa. If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
     * operations.
     */
    /** 
    返回此Map中所包含的所有Key的 Set<K>。 
    如果map发生修改,则Set也会对应的修改。
    如果在对 set 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外),则迭代结果是不确定的。
    该 set 支持移除元素,通过Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作可从该映射中移除相应的映射关系。
    但是不支持 add 或 addAll 操作。 
    */ 
    public Set<K> keySet() {
        Set<K> ks = keySet;
        return (ks != null ? ks : (keySet = new KeySet()));// 如果keySet为null,则new KeySet()
    }
    
    /**
    KeySet的一些方法
    */
    private final class KeySet extends AbstractSet<K> {
        public Iterator<K> iterator() {
            return newKeyIterator();
        }
        public int size() {
            return size;
        }
        public boolean contains(Object o) {
            return containsKey(o);
        }
        public boolean remove(Object o) {
            return HashMap.this.removeEntryForKey(o) != null;
        }
        public void clear() {
            HashMap.this.clear();
        }
    }
    
    /**
     * Returns a {@link Collection} view of the values contained in this map.
     * The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa.  If the map is
     * modified while an iteration over the collection is in progress
     * (except through the iterator's own <tt>remove</tt> operation),
     * the results of the iteration are undefined.  The collection
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
     */
    /**
    同上,Value的集合Collection<V>
    */
    public Collection<V> values() {
        Collection<V> vs = values;
        return (vs != null ? vs : (values = new Values()));
    }
    
    private final class Values extends AbstractCollection<V> {
        public Iterator<V> iterator() {
            return newValueIterator();
        }
        public int size() {
            return size;
        }
        public boolean contains(Object o) {
            return containsValue(o);
        }
        public void clear() {
            HashMap.this.clear();
        }
    }
    
    /**
     * Returns a {@link Set} view of the mappings contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation, or through the
     * <tt>setValue</tt> operation on a map entry returned by the
     * iterator) the results of the iteration are undefined.  The set
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
     * <tt>clear</tt> operations.  It does not support the
     * <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a set view of the mappings contained in this map
     */
    /**
    同上,对象Entry的视图Set<Map.Entry<K,V>>
    */
    public Set<Map.Entry<K,V>> entrySet() {
        return entrySet0();
    }
    
    private Set<Map.Entry<K,V>> entrySet0() {
        Set<Map.Entry<K,V>> es = entrySet;
        return es != null ? es : (entrySet = new EntrySet());
    }
    
    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public Iterator<Map.Entry<K,V>> iterator() {
            return newEntryIterator();
        }
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<K,V> e = (Map.Entry<K,V>) o;
            Entry<K,V> candidate = getEntry(e.getKey());
            return candidate != null && candidate.equals(e);
        }
        public boolean remove(Object o) {
            return removeMapping(o) != null;
        }
        public int size() {
            return size;
        }
        public void clear() {
            HashMap.this.clear();
        }
    }

     重要方法Methods:

    //创建一个空的HashMap,指定capacity和loadFactor的
    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;
        while (capacity < initialCapacity)
            capacity <<= 1;
        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
        init();
    }
    //创建一个空的HashMap,指定capacity,默认loadFactor
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    //创建一个空的HashMap,默认capacity,loadFactor
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }
    //创建一个新的HashMap,键值对与m相同
    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.)
    给之类初始化的方法,该方法用于HashMap初始化之后,插入元素之前
    */
    void init() {}
    
    /**
     * Applies a supplemental hash function to a given hashCode, 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.
     根据给定的hashCode计算hash值(也就是应该存储在数组中的索引)
     可能是尽可能使之分布均匀,但具体不明。
     */
    static int hash(int h) {
        // 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);//>>>:无符号右移,忽略符号位,空位都以0补齐;>>:右移运算符
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
    
    /**
     * 再根据hash值和数组长度算出索引值
     * 由于length是2的n次幂,所以h & (length-1)相当于h % length。 
     * 对于length,其2进制表示为1000...0,那么length-1为0111...1。 
     * 那么对于任何小于length的数h,该式结果都是其本身h。 
     * 对于h = length,该式结果等于0。 
     * 对于大于length的数h,则和0111...1位与运算后, 
     * 比0111...1高或者长度相同的位都变成0, 
     * 相当于减去j个length,该式结果是h-j*length, 
     * 所以相当于h % length。 
     * 其中一个很常用的特例就是h & 1相当于h % 2。 
     * 这也是为什么length只能是2的n次幂的原因,为了优化。 
     */  
    static int indexFor(int h, int length) {
        return h & (length-1);
    }
    //返回map中键值对的数量
    public int size() {
        return size;
    }
    //判断map是否为空,返回true/false
    public boolean isEmpty() {
        return size == 0;
    }
    
    /**
    根据key查询对应的value,如果找到返回value,否则返回null
    1,计算key的hashcode
    2,根据hashCode再算出索引值i,indexFor(hash, table.length)
    3,根据索引i得到table[i],再逐个查询table[i]中的entry.key
    */
    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());//计算key的hashcode,然后再算出索引值i,得到table[i],然后再逐个查询table[i]中的entry.key
        for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {//e = e.next可以看出数组+链表的形式
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }
    
    //如果key为null的时候,逐个查询table[0]中的Entry,如果e.key == null,则返回e.value,否则返回null。这也说明HashMap中key是可以为null,而HashTable是不可以的
    private V getForNullKey() {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null)
                return e.value;
        }
        return null;
    }
    
    //判断Map中是否含有 键 = key 的对象,有返回true,否则返回false
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }
    //根据key查询Entry,并返回
    final Entry<K,V> getEntry(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }
    /**
    往Map中put一个键值对,如果key存在,则旧值(引用)会被替代并返回
    1,根据key的hashCode计算hash值
    2,根据hash值计算索引值
    */
    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);//如果key为null
        int hash = hash(key.hashCode());//根据key的hashCode计算hash值
        int i = indexFor(hash, table.length);//根据hash值计算索引值
        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;
            }
        }
    
        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
    
    //key为null时的put方法,放在table[0]中
    private V putForNullKey(V value) {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(0, null, value, 0);
        return null;
    }
    
    //put,是否需要创建一个新的键值对
    private void putForCreate(K key, V value) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);
        /**
         * Look for preexisting entry for key.  This will never happen for
         * clone or deserialize.  It will only happen for construction if the
         * input Map is a sorted map whose ordering is inconsistent w/ equals.
         */
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {//如果存在,则不需要创建
                e.value = value;
                return;
            }
        }
        //不存在,则创建新的Entry
        createEntry(hash, key, value, i);
    }
    
    //根据Map来判断
    private void putAllForCreate(Map<? extends K, ? extends V> m) {
        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<? extends K, ? extends V> e = i.next();
            putForCreate(e.getKey(), e.getValue());
        }
    }
    /**
     * Rehashes the contents of this map into a new array with a
     * larger capacity.  This method is called automatically when the
     * number of keys in this map reaches its threshold.
     *
     * If current capacity is MAXIMUM_CAPACITY, this method does not
     * resize the map, but sets threshold to Integer.MAX_VALUE.
     * This has the effect of preventing future calls.
     *
     * @param newCapacity the new capacity, MUST be a power of two;
     *        must be greater than current capacity unless current
     *        capacity is MAXIMUM_CAPACITY (in which case value
     *        is irrelevant).
     */
    /**
    根据newCapacity resize HashMap(所有对象需要重新计算Hash值,很耗时)
    */ 
    void resize(int newCapacity) {
        Entry[] oldTable = table;//oldTable
        int oldCapacity = oldTable.length;//oldCapacity
        if (oldCapacity == MAXIMUM_CAPACITY) {//如果已经是最大capacity,直接返回
            threshold = Integer.MAX_VALUE;//threshold = Integer.MAX_VALUE
            return;
        }
    
        Entry[] newTable = new Entry[newCapacity];//创建新表
        transfer(newTable);//数据转移
        table = newTable;//table = newTable
        threshold = (int)(newCapacity * loadFactor);//重新定义阈值
    }
    /**
     * 将当前table中的所有的entries 转移到newTable
     */
    void transfer(Entry[] newTable) {
        Entry[] src = table;
        int newCapacity = newTable.length;//capacity = table.length; size is size
        for (int j = 0; j < src.length; j++) {
            Entry<K,V> e = src[j];
            if (e != null) {
                src[j] = null;
                do {
                    Entry<K,V> next = e.next;
                    int i = indexFor(e.hash, newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }
    
    /**
    Copies all of the mappings from the specified map to this map. These mappings will replace any mappings that this map had for any of the keys currently in the specified map.
    将制定的Map m中的键值对复制(或替换)到当前map中
    */
    public void putAll(Map<? extends K, ? extends V> m) {
        int numKeysToBeAdded = m.size();
        if (numKeysToBeAdded == 0)
            return;
        /*
         * Expand the map if the map if the number of mappings to be added
         * is greater than or equal to threshold.  This is conservative; the
         * obvious condition is (m.size() + size) >= threshold, but this
         * condition could result in a map with twice the appropriate capacity,
         * if the keys to be added overlap with the keys already in this map.
         * By using the conservative calculation, we subject ourself
         * to at most one extra resize.
         */
        //如果(m.size() + size) >= threshold,则需要进行扩容(所有对象需要重新计算Hash值,很耗时) 
        if (numKeysToBeAdded > threshold) {
            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
            if (targetCapacity > MAXIMUM_CAPACITY)
                targetCapacity = MAXIMUM_CAPACITY;
            int newCapacity = table.length;
            while (newCapacity < targetCapacity)
                newCapacity <<= 1;
            if (newCapacity > table.length)
                resize(newCapacity);
        }
    
        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<? extends K, ? extends V> e = i.next();
            put(e.getKey(), e.getValue());
        }
    }
    
    /**
    根据Key,移除对应的Entry e,并返回e.value
    如果没有找到,则返回null
    */
    public V remove(Object key) {
        Entry<K,V> e = removeEntryForKey(key);
        return (e == null ? null : e.value);
    }
    /**
    * Removes and returns the entry associated with the specified key
    * in the HashMap.  Returns null if the HashMap contains no mapping
    * for this key.
    */
    final Entry<K,V> removeEntryForKey(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);
        Entry<K,V> prev = table[i];
        Entry<K,V> e = prev;
    
        while (e != null) {
            Entry<K,V> next = e.next;
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k)))) {
                modCount++;
                size--;
                if (prev == e)
                    table[i] = next;
                else
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
            prev = e;
            e = next;
        }
        return e;
    }
    
    /**
    * 移除指定的(Map.Entry<K,V>) o,不过还是根据entry.getKey()去查询,查询到返回Entry e,否则返回null
    */
    final Entry<K,V> removeMapping(Object o) {
        if (!(o instanceof Map.Entry))
            return null;
        
        Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
        Object key = entry.getKey();
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);
        Entry<K,V> prev = table[i];
        Entry<K,V> e = prev;
    
        while (e != null) {
            Entry<K,V> next = e.next;
            if (e.hash == hash && e.equals(entry)) {
                modCount++;
                size--;
                if (prev == e)
                    table[i] = next;
                else
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
            prev = e;
            e = next;
        }
    
        return e;
    }
    
    //置空Map
    public void clear() {
        modCount++;
        Entry[] tab = table;
        for (int i = 0; i < tab.length; i++)
            tab[i] = null;
        size = 0;
    }
    
    /**
    判断Map中是否含有一个或多个Entry e,满足e.value = value
    */
    public boolean containsValue(Object value) {
        if (value == null)
            return containsNullValue();
    
        Entry[] tab = table;
        for (int i = 0; i < tab.length ; i++)
            for (Entry e = tab[i] ; e != null ; e = e.next)
                if (value.equals(e.value))
                    return true;
        return false;
    }
    
    private boolean containsNullValue() {
        Entry[] tab = table;
        for (int i = 0; i < tab.length ; i++)
            for (Entry e = tab[i] ; e != null ; e = e.next)
                if (e.value == null)
                    return true;
        return false;
    }
    
    /**
     * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and values themselves are not cloned.
     shallow copy,键值对不复制
     * @return a shallow copy of this map
     */
    public Object clone() {
        HashMap<K,V> result = null;
        try {
            result = (HashMap<K,V>)super.clone();
        } catch (CloneNotSupportedException e) {
            // assert false;
        }
        result.table = new Entry[table.length];
        result.entrySet = null;
        result.modCount = 0;
        result.size = 0;
        result.init();
        result.putAllForCreate(this);
    
        return result;
    }
    
    /**
    * Adds a new entry with the specified key, value and hash code to
    * the specified bucket.  It is the responsibility of this
    * method to resize the table if appropriate.
    *
    * Subclass overrides this to alter the behavior of put method.
    */
    /**
    在指定的位置table[bucketIndex],添加一个指定Key 和 Value的对象Entry
    */
    void addEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];//旧值
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        // 如果达到阈值,则2倍扩容
        if (size++ >= threshold)
            resize(2 * table.length);
    }
    /**
    根据给定的值,创建新键值对
    */
    void createEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        size++;
    }
    
    /**
     * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
     * serialize it).
     *
     * @serialData The <i>capacity</i> of the HashMap (the length of the
     *           bucket array) is emitted (int), followed by the
     *           <i>size</i> (an int, the number of key-value
     *           mappings), followed by the key (Object) and value (Object)
     *           for each key-value mapping.  The key-value mappings are
     *           emitted in no particular order.
     */
    /**
    对象序列化
    */
     private void writeObject(java.io.ObjectOutputStream s) throws IOException {
        Iterator<Map.Entry<K,V>> i = (size > 0) ? entrySet0().iterator() : null;
    
        // Write out the threshold, loadfactor, and any hidden stuff
        s.defaultWriteObject();
    
        // Write out number of buckets
        s.writeInt(table.length);
    
        // Write out size (number of Mappings)
        s.writeInt(size);
    
            // Write out keys and values (alternating)
        if (i != null) {
            while (i.hasNext()) {
            Map.Entry<K,V> e = i.next();
            s.writeObject(e.getKey());
            s.writeObject(e.getValue());
            }
        }
    }
    private static final long serialVersionUID = 362498820763181265L;
    
    /**
    * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
    * deserialize it).
    */
    /**
    读取序列化对象
    */
    private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
        // Read in the threshold, loadfactor, and any hidden stuff
        s.defaultReadObject();
    
        // Read in number of buckets and allocate the bucket array;
        int numBuckets = s.readInt();
        table = new Entry[numBuckets];
    
        init();  // Give subclass a chance to do its thing.
    
        // Read in size (number of Mappings)
        int size = s.readInt();
    
        // Read the keys and values, and put the mappings in the HashMap
        for (int i=0; i<size; i++) {
            K key = (K) s.readObject();
            V value = (V) s.readObject();
            putForCreate(key, value);
        }
    }
    
        // These methods are used when serializing HashSets
        int   capacity()     { return table.length; }
        float loadFactor()   { return loadFactor;   }

    遗留的问题:

    (1)关于hashCode的计算,以及计算hash值得算法为什么是这样写的?:

    //计算hash值
    static int hash(int h) {        
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
    //计算索引值
    static int indexFor(int h, int length) {
        return h & (length-1);
    }
  • 相关阅读:
    ubuntu18.04安装dash-to-dock出错的问题
    使用SVN+Axure RP 8.0创建团队项目
    软件工程实践专题第一次作业
    C#单问号(?)与双问号(??)
    词根 ten 展开 持有 /tin/tent/tain “to hold”
    vscode 对js文件不格式化的修正方案 settings.json
    open cv java 可以 对图片进行分析,得到数据。考试答题卡 2B铅笔涂黑嘎达 识别
    bounties 赏金 bon = good 来自法语 bonjour 早上好
    class cl表示 汇聚 集合 ss表示 阴性 这里表示抽象
    git svn 提交代码日志填写规范 BUG NEW DEL CHG TRP gitz 日志z
  • 原文地址:https://www.cnblogs.com/lemon-now/p/5204919.html
Copyright © 2011-2022 走看看