定义
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable{static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //默认初始化容积,就是默认数组的长度为 16static 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; //最小的树化容积
}存储结构
         每个 Node[] 数组中的元素被称为桶  bucket ,一个桶对应一个  hash  映射的值,例如  0 、 1 、 2 、 3 ,相同的 hash  映射值可能会出现不同的  key  值,因此针对桶采用链表结构存储  hash  映射值相同的所有数据【 JDK1.8  在单个链表长度大于阈值  8  时会自动转换位红黑树;当删除结点使某个红黑树中节点数小于阈值  6  时会自动从 红黑树蜕化成链表结构】 
 
static class Node<K,V> implements Map.Entry<K,V> {  // 是 Map 中所存储 Entry 的实现类final int hash;  // 对应的 hash 值final K key;  // 存储对应的 key 值V value;  // 存储对应的 value 值Node<K,V> next;  // 指向下一个节点的单向链数据存储
transient Node<K,V>[] table;
相关参数 :
 capacity  :容积值标识当前输入的容量,始终保持是  2  的  n  次方,可以扩容,扩容后的数组大小为原始数组大小的  2  倍  
   loadFactor : 负载因子,默认是  0.75 ,注意这个值在使用链表法的实现中可以大于  1 ,负载因子越大越节约空间,但是导致  hash  冲突概率提高,链表的长度会增加。查询性能和空间浪费均衡下选取  0.75  
   threshold  :扩容阈值,等于  capacity*loadFactor 
  底层实现
 JDK1.7 版本:  
          hashmap 底层采用的是【 Entry  数组和链表】实现的。向一个链表中添加数据时采用的是头插法,在多线程并发操作中会有环形链的问题。 
  JDK1.8 版本 : 
          hashmap 使用  Node  类型的【数组和链表以及红黑树】实现的, Node  用于链表,红黑树使用的是  TreeNode树化处理 。 向一个链表中插入数据采用的是尾插法,可以避免环形链问题,但是并不是解决了线程安全问题,仍旧会有扩 容处理的  rehash  时的死循环问题、脏读丢失数据问题、 size  不准确问题。 
  实现原理
散列
         Hash 哈希算法的意义在于提供了一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系。散列表又称为哈希表。  
          散列表算法的基本思想是:以结点的关键字为自变量,通过一定的函数关系(散列函数)计算出对应的函数值,以这个值作为该结点存储在散列表中地址。 
  构造器
public HashMap() {//没有进行数组的初始化操作,只设置了负载因子值为0.75this.loadFactor = DEFAULT_LOAD_FACTOR;
}public HashMap(int initialCapacity) {
//可以在创建 HashMap 对象时直接设置初始化容器值,负载因子默认0.75。this(initialCapacity, DEFAULT_LOAD_FACTOR);
}public HashMap(int initialCapacity, float loadFactor) {//并没有初始化数组if (initialCapacity < 0)throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);//如果初始化容积值小于0,则抛出运行时异常中断执行if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;//如果初始化容积值大于2的30次方,则初始化容积值为 2^30if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Illegal load factor: " + loadFactor);//负载因子值要求大于0,否则运行时异常。为了减少hash冲突的概率,一般建议小于1。this.loadFactor = loadFactor;this.threshold = tableSizeFor(initialCapacity);//根据传入的初始化容积值,获取新合法的容积值,该值应该是>=initialCapacity的最小2次幂。
}static final int tableSizeFor(int cap) {int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}Put方法
public V put(K key, V value) {return putVal(hash(key), key, value, false, true);
//参数 1 获取 key 的新 hash 值
//参数 2 为 key
//参数 3为 value
//参数 4 为 true 不更改现有值 false 更改现有值,参数 5 为 false 则创建模式 true 追加模式
}static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
} 