map是一种键值映射的数据结构,键不允许重复 
介绍一些java当中实现map的关键的几个方法,包括get,put,resize
AbstractMap 该类是其他具体map类的父类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public  boolean  containsKey (Object key)          Iterator<Map.Entry<K,V>> i = entrySet().iterator();         if  (key==null ) {             while  (i.hasNext()) {                 Entry<K,V> e = i.next();                 if  (e.getKey()==null )                     return  true ;             }         } else  {             while  (i.hasNext()) {                 Entry<K,V> e = i.next();                 if  (key.equals(e.getKey()))                     return  true ;             }         }         return  false ;     } 
HashMap HashMap是一个很常用很重要的工具类,看看它是怎么实现的   
它是由数组+链表+红黑树实现的,也就是解决hash的冲突的办法是链地址法
数组的长度永远是2的幂(自有作用)  
允许键值null
基本成员属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public  class  HashMap <K ,V > extends  AbstractMap <K ,V >    implements  Map <K ,V >, Cloneable , Serializable   {           static  final  int  DEFAULT_INITIAL_CAPACITY = 1  << 4 ;            static  final  int  MAXIMUM_CAPACITY = 1  << 30 ;            static  final  float  DEFAULT_LOAD_FACTOR = 0.75f ;            static  final  int  TREEIFY_THRESHOLD = 8 ;            static  final  int  UNTREEIFY_THRESHOLD = 6 ;            static  final  int  MIN_TREEIFY_CAPACITY = 64 ;          transient  Node<K,V>[] table;     transient  Set<Map.Entry<K,V>> entrySet;          transient  int  size;          transient  int  modCount;          int  threshold;     final  float  loadFactor;     } 
Node类 键值结构在map里是由Node来存储的1 2 3 4 5 6 7 8 9 10 11 12 13 static  class  Node <K ,V > implements  Map .Entry <K ,V >                  final  int  hash;         final  K key;         V value;         Node<K,V> next;          public  final  int  hashCode ()               return  Objects.hashCode(key) ^ Objects.hashCode(value);         } } 
HashMap具体的方法 key的hash值:高16位与低16为进行亦或运算
1 2 3 4 static  final  int  hash (Object key)          int  h;         return  (key == null ) ? 0  : (h = key.hashCode()) ^ (h >>> 16 );     } 
求不小于一个数的最小的2^n,例如num=15,返回16;num=16,返回16。
1 2 3 4 5 6 7 8 9 10 11 12 13 static  final  int  tableSizeFor (int  cap)                   int  n = cap - 1 ;                  n |= n >>> 1 ;                  n |= n >>> 2 ;         n |= n >>> 4 ;         n |= n >>> 8 ;         n |= n >>> 16 ;                  return  (n < 0 ) ? 1  : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1 ;     } 
构造函数(多种),只介绍一种
1 2 3 4 5 6 7 8 9 10 11 12 13 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);         this .loadFactor = loadFactor;         this .threshold = tableSizeFor(initialCapacity);     } 
获取Node的方法:流程是:先判断数组相应位置是否为空,在判断第一个节点,再根据是树还是链表查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 ) {                          if  (first.hash == hash &&                  ((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 );             }         }         return  null ;     } 
put Node的方法,通过尾插法;如果没有初始化先初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 )             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 )                              treeifyBin(tab, hash);                         break ;                     }                                          if  (e.hash == hash &&                         ((k = e.key) == key || (key != null  && key.equals(k))))                         break ;                     p = e;                 }             }                          if  (e != null ) {                  V oldValue = e.value;                 if  (!onlyIfAbsent || oldValue == null )                     e.value = value;                 afterNodeAccess(e);                 return  oldValue;             }         }                  ++modCount;                  if  (++size > threshold)             resize();         afterNodeInsertion(evict);                  return  null ;     } 
扩容:一个table[i]上的节点扩容后只可能在两个位置,一个是原位置,一个是oldCap+i
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 final  Node<K,V>[] resize() {        Node<K,V>[] oldTab = table;         int  oldCap = (oldTab == null ) ? 0  : oldTab.length;         int  oldThr = threshold;         int  newCap, newThr = 0 ;                  if  (oldCap > 0 ) {             if  (oldCap >= MAXIMUM_CAPACITY) {                 threshold = Integer.MAX_VALUE;                 return  oldTab;             }             else  if  ((newCap = oldCap << 1 ) < MAXIMUM_CAPACITY &&                      oldCap >= DEFAULT_INITIAL_CAPACITY)                 newThr = oldThr << 1 ;          }         else  if  (oldThr > 0 )              newCap = oldThr;         else  {                            newCap = DEFAULT_INITIAL_CAPACITY;             newThr = (int )(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);         }         if  (newThr == 0 ) {             float  ft = (float )newCap * loadFactor;             newThr = (newCap < MAXIMUM_CAPACITY && ft < (float )MAXIMUM_CAPACITY ?                       (int )ft : Integer.MAX_VALUE);         }         threshold = newThr;         @SuppressWarnings ({"rawtypes" ,"unchecked" })             Node<K,V>[] newTab = (Node<K,V>[])new  Node[newCap];         table = newTab;                  if  (oldTab != null ) {                          for  (int  j = 0 ; j < oldCap; ++j) {                 Node<K,V> e;                 if  ((e = oldTab[j]) != null ) {                     oldTab[j] = null ;                                          if  (e.next == null )                         newTab[e.hash & (newCap - 1 )] = e;                     else  if  (e instanceof  TreeNode)                         ((TreeNode<K,V>)e).split(this , newTab, j, oldCap);                                          else  {                                                   Node<K,V> loHead = null , loTail = null ;                         Node<K,V> hiHead = null , hiTail = null ;                         Node<K,V> next;                         do  {                             next = e.next;                                                                                                                                                 if  ((e.hash & oldCap) == 0 ) {                                 if  (loTail == null )                                     loHead = e;                                 else                                      loTail.next = e;                                 loTail = e;                             }                             else  {                                 if  (hiTail == null )                                     hiHead = e;                                 else                                      hiTail.next = e;                                 hiTail = e;                             }                         } while  ((e = next) != null );                         if  (loTail != null ) {                             loTail.next = null ;                             newTab[j] = loHead;                         }                         if  (hiTail != null ) {                             hiTail.next = null ;                             newTab[j + oldCap] = hiHead;                         }                     }                 }             }         }         return  newTab;     }