java 集合学习之hashMap

    xiaoxiao2021-12-10  16

    1、hashMap类继承关系

    public class HashMap<K,V> extends AbstractMap<K,V>

        implements Map<K,V>, Cloneable, Serializable

    存放示意图

    由此可以看出hash值一样的节点会被存放在同一条链表上,比原始遍历equals查找效率高(hash值相等的分为一组作为一个链表,在对该链表进行遍历查找)

    重要属性:

    1、static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;默认容量,必须是2的指数

    2、static final int MAXIMUM_CAPACITY = 1 << 30;最大容量

    3、static final float DEFAULT_LOAD_FACTOR = 0.75f;加载因子

    4、static final int TREEIFY_THRESHOLD = 8;

    5、static final int UNTREEIFY_THRESHOLD = 6;

    6、static final int MIN_TREEIFY_CAPACITY = 64;

    7、transient Node<K,V>[] table;

    重要方法:

    1、通过key获取value

    public V get(Object key) {         Node<K,V> e;         return (e = getNode(hash(key), key)) == null ? null : e.value;     }

    static final int hash(Object key) {         int h;         return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);     }

    final Node<K,V> getNode(int hash, Object key) {         Node<K,V>[] tab; Node<K,V> first, e; int n; K k;         if ((tab = table) != null && (n = tab.length) > 0 &&             (first = tab[(n - 1) & hash]) != null) {//根据n-1*hash值找到对应key存放的节点在数组(table)中的index,如上图的first节点             if (first.hash == hash && // always check first node                 ((k = first.key) == key || (key != null && key.equals(k))))                 return first;             if ((e = first.next) != null) {                 if (first instanceof TreeNode)                     return ((TreeNode<K,V>)first).getTreeNode(hash, key);                 do {                     if (e.hash == hash &&                         ((k = e.key) == key || (key != null && key.equals(k))))                         return e;                 } while ((e = e.next) != null); 此处在链上查找对应key的node             }         }         return null;     }

    2、向hashMap中存放一个node

    public V put(K key, V value) {         return putVal(hash(key), key, value, false, true);     }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

                       boolean evict) {         Node<K,V>[] tab; Node<K,V> p; int n, i;         if ((tab = table) == null || (n = tab.length) == 0)             n = (tab = resize()).length;         if ((p = tab[i = (n - 1) & hash]) == null)//根据hash值找到对应链表的表头节点             tab[i] = newNode(hash, key, value, null);         else {             Node<K,V> e; K k;             if (p.hash == hash &&                 ((k = p.key) == key || (key != null && key.equals(k))))                 e = p;             else if (p instanceof TreeNode)                 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);             else {                 for (int binCount = 0; ; ++binCount) {                     if ((e = p.next) == null) {                         p.next = newNode(hash, key, value, null);                         if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st                             treeifyBin(tab, hash);                         break;                     }                     if (e.hash == hash &&//如果链表中存在放入的key,则在后面替换原有的value                         ((k = e.key) == key || (key != null && key.equals(k))))                         break;                     p = e;//重置起始引用                 }             }             if (e != null) { // existing mapping for key                 V oldValue = e.value;                 if (!onlyIfAbsent || oldValue == null)                     e.value = value;//替换                 afterNodeAccess(e);                 return oldValue;             }         }         ++modCount;         if (++size > threshold)             resize();         afterNodeInsertion(evict);         return null;     }

    3、根据查询map是否含有value对象的节点

    public boolean containsValue(Object value) {         Node<K,V>[] tab; V v;         if ((tab = table) != null && size > 0) {             for (int i = 0; i < tab.length; ++i) {//遍历table数组,对应找出链表头                 for (Node<K,V> e = tab[i]; e != null; e = e.next) {//遍历链表                     if ((v = e.value) == value ||                         (value != null && value.equals(v)))                         return true;                 }             }         }         return false;     }

    4、清空map

    public void clear() {         Node<K,V>[] tab;         modCount++;         if ((tab = table) != null && size > 0) {             size = 0;             for (int i = 0; i < tab.length; ++i)                 tab[i] = null;//此循环只在遍历数组,置空表头,链表其他元素并未显式置空,gc回收         }     }

    备注:1、必需熟悉泛型概念

       2、a|b=>其结果   较大者<=result<=a+b;a&b=>其结果  0<=result<=较小者

     

    学习资料:

    http://www.cnblogs.com/devinzhang/archive/2012/01/13/2321481.html

    http://www.cnblogs.com/ITtangtang/p/3948406.html

    转载请注明原文地址: https://ju.6miu.com/read-700337.html

    最新回复(0)