java8源码详解--HashMap
2018-03-10 14:00
525 查看
HashMap详解
标签: java8源码欢迎 start
HashMap的关系图
HashMap的特点
HashMap类签名:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {}
特点:
1. HashMap 继承自AbstractMap抽象类,实现了Map接口.以键值对存储信息. 2. HashMap 的键不能重复,且可以为null,最多只有一个键为null. 其值可以重复,且可以为null,可以多个对象为null. 3. HashMap 是线程不安全的. 4. HashMap 的键值对是无序的.
HashMap的结构介绍
其成员变量介绍* DEFAULT_INITIAL_CAPACITY : 默认初始容量 = 16 * MAXIMUM_CAPACITY :最大容量 = 2 的 30 次方 * DEFAULT_LOAD_FACTOR : 默认增长系数 = 0.75f * int size : HashMap 大小 * int threshold : 阈值.用于判断是否需要调整HashMap的容量(threshold = 容 量*加载因子) * Set<Map.Entry<K,V>> entrySet : 键值对集合 * Node<K,V>[] table : 存储新的Node数组 * int modCount : 修改次数(用于触发快速失败机制)
2.内部类
Node<K,V>介绍
static class Node<K,V> implements Map.Entry<K,V> {//继承自Map.Entry<K,V> 实现其方法 final int hash; final K key; V value; Node<K,V> next; //指向下一个Node<K,V> .由此可知,HashMap的Node<K,V>是个单向的链表 Node(int hash, K key, V value, Node<K,V> next) {//构造函数 this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } }
通过常用方法了解HashMap的实现原理
HashMap的构造方法public HashMap() {//空的构造方法 this.loadFactor = DEFAULT_LOAD_FACTOR;//初始化增长系数 //所有的属性都是默认值 } public HashMap(int initialCapacity) { //初始化指定容量的构造方法 this(initialCapacity, DEFAULT_LOAD_FACTOR); } 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); }
2.
put(K key,V value);方法
----------------put(K,V)-------------------------- public V put(K key, V value) { //调用putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) 方法 return putVal(hash(key), key, value, false, true); } --------------putVal(···)方法------------------- final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; //如果table为空,则通过resize()方法重新创建一个Node<K,V>复制给tab 这里已经把 table 赋值给 tab if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //通过 数组下标最大值 与 hash 的与操作,返回数组下标,并取出值赋给 节点 p,如果p为空,则新建Node节点,并赋值给tab[i] if ((p = tab[i = (n - 1) & hash]) == null) t 4000 ab[i] = newNode(hash, key, value, null); else {//如果p不会空,即,添加的元素已经存在,进入此判断 Node<K,V> e; K k; //如果p的hash和key等于传进来的key和p.hash 或者 key 不为空且 p.key等于传进来的key,则 把 p 赋值给 e. //--------------------------未读--------------------------- 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 && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } //--------------------------------------------------- if (e != null) { // 如果e != null 说明在当前容器中,存在一个相同的key值,于是替换key所对应的value V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e);//空方法,留着给LinkedHashMap调用 return oldValue; } } //修改次数 + 1 ++modCount; if (++size > threshold)//如果size > 阈值,则重新改变大小. resize(); afterNodeInsertion(evict);//空方法,留着给LinkedHashMap调用 return null; }
附上整个put()的逻辑图
HashMap源码太难了,的确还讲不好.推荐几个好的关于HashMap源码解读的文章
优秀的HashMap 的源码解读的文章
简书Github 1
Github 2
cnblog
相关文章推荐
- java8源码详解--HashMap-put逻辑
- 【Java】HashMap源码分析——常用方法详解
- Java 1.8 HashMap 源码中 put()方法详解
- Java集合:HashMap使用详解及源码分析
- 【Java入门提高篇】Day24 Java容器类详解(七)HashMap源码分析(下)
- Java中HashMap详解 - HashMap源码及实现原理
- 【Java入门提高篇】Day22 Java容器类详解(五)HashMap源码分析(上)
- java中HashMap详解(从源码角度看内部实现)
- Java集合2-HashMap详解(含源码分析)
- 【Java入门提高篇】Day23 Java容器类详解(六)HashMap源码分析(中)
- java_集合体系之WeakHashMap详解、源码及示例——11
- java集合13--WeakHashMap源码详解
- 深入Java基础(四)--哈希表(1)HashMap应用及源码详解
- java_集合体系之HashMap详解、源码及示例——09
- Java集合详解四:HashMap源码详解
- Java集合——TreeMap源码详解
- Java之hashCode与equals深度剖析与源码详解
- java源码分析---HashMap
- 基础知识(二) LinkedHashMap 源码详解
- java中HashMap详解