HashMap简介

HashMap是基于哈希表实现的,每一个元素都是一个key-value对(并且允许未null),其内部通过单链表解决冲突问题,容量不足(超过了阈值)时,同样会自动增长。

HashMap是非线程安全的(Hashtable是线程安全,且不允许null值),只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。

HashMap实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。

首先通过图片大致看一下结构:

首先我们要非常注意的一点,在Java框架集合那篇文章中也提到了!!!

默认维护的Entry

  /** @hide */  // Android added. 被隐藏的api,安卓添加static class HashMapEntry<K,V> implements Map.Entry<K,V> {final K key;V value;HashMapEntry<K,V> next;int hash;/*** Creates new entry.* 默认维护的HashMapEntry* 方法和我们常用的HashMap的很相近*/HashMapEntry(int h, K k, V v, HashMapEntry<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;}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;}public final int hashCode() {return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());}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.* 这个方法在key已存在,且被重新赋值的时候*/void recordAccess(HashMap<K,V> m) {}/*** This method is invoked whenever the entry is* removed from the table.* 在被删除的时候调用*/void recordRemoval(HashMap<K,V> m) {}}

下面让我们来解析源码,注释很清晰,不再多余解释!

package java.util;
import java.io.*;    public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable
{    /** 默认的初始容量(容量为HashMap中槽的数目)是4,hashset默认维护了一个hashmap,出事容量是16,且实际容量必须是2的整数次幂。  MUST be a power of two  */static final int DEFAULT_INITIAL_CAPACITY = 4;    // 最大容量(必须是2的幂且小于2的30次方,传入容量过大将被这个值替换)    MUST be a power of two <= 1<<30static final int MAXIMUM_CAPACITY = 1 << 30;    // 默认加载因子为0.75   static final float DEFAULT_LOAD_FACTOR = 0.75f;    // 存储数据的Entry数组,长度是2的幂。    // HashMap采用链表法解决冲突,每一个HashMapEntry本质上是一个单向链表    //此处创建了一个空表,而不是原来的声明一个transient Entry[] table在构造方法中实例化static final HashMapEntry<?,?>[] EMPTY_TABLE = {};//容量不够时的新的表
transient HashMapEntry<K,V>[] table = (HashMapEntry<K,V>[]) EMPTY_TABLE; // HashMap的底层数组中已用槽的数量    transient int size;    // HashMap的阈值,用于判断是否需要调整HashMap的容量(threshold = 容量*加载因子)    int threshold;    // 加载因子实际大小    final float loadFactor;    // HashMap被改变的次数    transient volatile int modCount;    // 指定“容量大小”和“加载因子”的构造函数    public HashMap(int initialCapacity, float loadFactor) {    if (initialCapacity < 0)    throw new IllegalArgumentException("Illegal initial capacity: " +    initialCapacity);    // HashMap的最大容量只能是MAXIMUM_CAPACITY    if (initialCapacity > MAXIMUM_CAPACITY)    initialCapacity = MAXIMUM_CAPACITY;    //加载因此不能小于0  if (loadFactor <= 0 || Float.isNaN(loadFactor))    throw new IllegalArgumentException("Illegal load factor: " +    loadFactor);    /*  下面是java的做法---------找出“大于initialCapacity”的最小的2的幂    int capacity = 1;    while (capacity < initialCapacity)    capacity <<= 1;    设置“加载因子”    this.loadFactor = loadFactor;    设置“HashMap阈值”,当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。    threshold = (int)(capacity * loadFactor);    创建Entry数组,用来保存数据    table = new Entry[capacity];   */ // Android-Note: We always use the default loadfactor of 0.75f. 我们一直采用默认的0.75,这是一个艰难的决定,虽然很可能产生错误threshold = initialCapacity;init();    }    //init方法什么都没做void init() {}// 指定“容量大小”的构造函数    public HashMap(int initialCapacity) {    this(initialCapacity, DEFAULT_LOAD_FACTOR);    }    // 默认构造函数。    public HashMap() {    /* 老版本的设置方法,安卓直接采用默认的0.75设置“加载因子”为默认加载因子0.75    this.loadFactor = DEFAULT_LOAD_FACTOR;    // 设置“HashMap阈值”,当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。    threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);    // 创建Entry数组,用来保存数据    table = new Entry[DEFAULT_INITIAL_CAPACITY];       */  this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);}    // 包含“子Map”的构造函数    public HashMap(Map<? extends K, ? extends V> m) {    this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,  DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);    // 将m中的全部元素逐个添加到HashMap中    putAllForCreate(m);    }    //看方法名字,找出“大于number”的最小的2的幂 private static int roundUpToPowerOf2(int number) {// assert number >= 0 : "number must be non-negative";int rounded = number >= MAXIMUM_CAPACITY? MAXIMUM_CAPACITY: (rounded = Integer.highestOneBit(number)) != 0? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded: 1;return rounded;}//实例化tableprivate void inflateTable(int toSize) {// Find a power of 2 >= toSizeint capacity = roundUpToPowerOf2(toSize);// Android-changed: Replace usage of Math.min() here because this method is// called from the <clinit> of runtime, at which point the native libraries// needed by Float.* might not be loaded.float thresholdFloat = capacity * loadFactor;if (thresholdFloat > MAXIMUM_CAPACITY + 1) {thresholdFloat = MAXIMUM_CAPACITY + 1;}threshold = (int) thresholdFloat;table = new HashMapEntry[capacity];}// 返回h在数组中的索引值,这里用&代替取模,旨在提升效率   // h & (length-1)保证返回值的小于length    static int indexFor(int h, int length) {    return h & (length-1);    }    public int size() {    return size;    }    public boolean isEmpty() {    return size == 0;    }    // 获取key对应的value    public V get(Object key) {    if (key == null)    return getForNullKey();    /* java中此方法 ,安卓已修改获取key的hash值    int hash = hash(key.hashCode());    // 在“该hash值对应的链表”上查找“键值等于key”的元素    for (Entry<K,V> e = table[indexFor(hash, table.length)];    e != null;    e = e.next) {    Object k;    //判断key是否相同  if (e.hash == hash && ((k = e.key) == key || key.equals(k)))    return e.value;    }  //没找到则返回null  return null;    */
return null == entry ? null : entry.getValue();//这里是调用了map的 getValue()方法}    // 获取“key为null”的元素的值    // HashMap将“key为null”的元素存储在table[0]位置,但不一定是该链表的第一个位置!    private V getForNullKey() {    for (Entry<K,V> e = table[0]; e != null; e = e.next) {    if (e.key == null)    return e.value;    }    return null; }    // HashMap是否包含key    public boolean containsKey(Object key) {    return getEntry(key) != null;    }    // 返回“键为key”的键值对    final Entry<K,V> getEntry(Object key) {    // 获取哈希值    // HashMap将“key为null”的元素存储在table[0]位置,“key不为null”的则调用hash()计算哈希值    // int hash = (key == null) ? 0 : hash(key.hashCode());   这是java中的方法 int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key);//特么的,这个方法也是醉了,找都找不到,估计和上面注释掉的是一个原理// 在“该hash值对应的链表”上查找“键值等于key”的元素    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;    }    // 将“key-value”添加到HashMap中    public V put(K key, V value) {    //安卓中添加了这个方法,用于初始化if (table == EMPTY_TABLE) {inflateTable(threshold);}// 若“key为null”,则将该键值对添加到table[0]中。    if (key == null)    return putForNullKey(value);    // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。    //  int hash = hash(key.hashCode());   int hash = sun.misc.Hashing.singleWordWangJenkinsHash(key); int i = indexFor(hash, table.length);    for (Entry<K,V> e = table[i]; e != null; e = e.next) {    Object k;    // 若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出!    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {    V oldValue = e.value;    e.value = value;    e.recordAccess(this);    return oldValue;    }    }    // 若“该key”对应的键值对不存在,则将“key-value”添加到table中    modCount++;  //将key-value添加到table[i]处  addEntry(hash, key, value, i);    return null;    }    // putForNullKey()的作用是将“key为null”键值对添加到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;    }    }    // 如果没有存在key为null的键值对,则直接题阿见到table[0]处!    modCount++;    addEntry(0, null, value, 0);    return null;    }    // 创建HashMap对应的“添加方法”,    // 它和put()不同。putForCreate()是内部方法,它被构造函数等调用,用来创建HashMap    // 而put()是对外提供的往HashMap中添加元素的方法。    private void putForCreate(K key, V value) {    int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key));  int i = indexFor(hash, table.length);    // 若该HashMap表中存在“键值等于key”的元素,则替换该元素的value值    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;    }    }    // 若该HashMap表中不存在“键值等于key”的元素,则将该key-value添加到HashMap中    createEntry(hash, key, value, i);    }    // 将“m”中的全部元素都添加到HashMap中。    // 该方法被内部的构造HashMap的方法所调用。    private void putAllForCreate(Map<? extends K, ? extends V> m) {    // java中利用迭代器将元素逐个添加到HashMap中,安卓利用增强for循环    /*   for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {    Map.Entry<? extends K, ? extends V> e = i.next();    */for (Map.Entry<? extends K, ? extends V> e : m.entrySet())//安卓修改putForCreate(e.getKey(), e.getValue());}    }    // 重新调整HashMap的大小,newCapacity是调整后的容量    void resize(int newCapacity) {    HashMapEntry[] oldTable = table;    int oldCapacity = oldTable.length;   //如果就容量已经达到了最大值,则不能再扩容,直接返回  if (oldCapacity == MAXIMUM_CAPACITY) {    threshold = Integer.MAX_VALUE;    return;    }    // 新建一个HashMap,将“旧HashMap”的全部元素添加到“新HashMap”中,    // 然后,将“新HashMap”赋值给“旧HashMap”。    HashMapEntry[] newTable = new Entry[newCapacity];    transfer(newTable);    table = newTable;    //  threshold = (int)(newCapacity * loadFactor);
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);//这是安卓修改后的,比较合理   }    // 将HashMap中的全部元素都添加到newTable中    void transfer(HashMapEntry[] newTable) {       int newCapacity = newTable.length;    for (HashMapEntry<K,V> e : table) {//安卓修改后的代码,比较高大上,此处原来是简单的for循环while(null != e) {HashMapEntry<K,V> next = e.next;int i = indexFor(e.hash, newCapacity);e.next = newTable[i];newTable[i] = e;e = next;}}}    // 将"m"的全部元素都添加到HashMap中    public void putAll(Map<? extends K, ? extends V> m) {    // 有效性判断    int numKeysToBeAdded = m.size();    if (numKeysToBeAdded == 0)    return;    //放置tabel表为空if (table == EMPTY_TABLE) {inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));}// 计算容量是否足够,    // 若“当前阀值容量 < 需要的容量”,则将容量x2。    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);    }    /* java通过迭代器,将“m”中的元素逐个添加到HashMap中。    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());    *///安卓put方法for (Map.Entry<? extends K, ? extends V> e : m.entrySet())put(e.getKey(), e.getValue());}    }    // 删除“键为key”元素    public V remove(Object key) {    Entry<K,V> e = removeEntryForKey(key);    return (e == null ? null : e.value);    }    // 删除“键为key”的元素    final Entry<K,V> removeEntryForKey(Object key) {    // 获取哈希值。若key为null,则哈希值为0;否则调用hash()进行计算    int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key));    int i = indexFor(hash, table.length);    HashMapEntry<K,V> prev = table[i];    HashMapEntry<K,V> e = prev;    // 删除链表中“键为key”的元素    // 本质是“删除单向链表中的节点”    while (e != null) {    HashMapEntry<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;    }    // 删除“键值对”    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);    HashMapEntry<K,V> prev = table[i];    HashMapEntry<K,V> e = prev;    // 删除链表中的“键值对e”    // 本质是“删除单向链表中的节点”    while (e != null) {    HashMapEntry<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;    }    // 清空HashMap,将所有的元素设为null    public void clear() {    modCount++;    Entry[] tab = table;    for (int i = 0; i < tab.length; i++)    tab[i] = null;    size = 0;    }    // 是否包含“值为value”的元素    public boolean containsValue(Object value) {    // 若“value为null”,则调用containsNullValue()查找    if (value == null)    return containsNullValue();    // 若“value不为null”,则查找HashMap中是否有值为value的节点。    HashMapEntry[] 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;    }    // 是否包含null值    private boolean containsNullValue() {    HashMapEntry[] tab = table;    for (int i = 0; i < tab.length ; i++)    for (HashMapEntrye = tab[i] ; e != null ; e = e.next)    if (e.value == null)    return true;    return false;    }    // 克隆一个HashMap,并返回Object对象    public Object clone() {    HashMap<K,V> result = null;    try {    result = (HashMap<K,V>)super.clone();    } catch (CloneNotSupportedException e) {    // assert false;    }    if (result.table != EMPTY_TABLE) {//安卓修改后的result.inflateTable(Math.min((int) Math.min(size * Math.min(1 / loadFactor, 4.0f),// we have limits...HashMap.MAXIMUM_CAPACITY),table.length));}result.entrySet = null;    result.modCount = 0;    result.size = 0;    result.init();    // 调用putAllForCreate()将全部元素添加到HashMap中    result.putAllForCreate(this);    return result;    }    // Entry是单向链表。    // 它是 “HashMap链式存储法”对应的链表。    // 它实现了Map.Entry 接口,即实现getKey(), getValue(), setValue(V value), equals(Object o), hashCode()这些函数    static class HashMapEntry<K,V> implements Map.Entry<K,V> {    final K key;    V value;    // 指向下一个节点    HashMapEntry<K,V> next;    final int hash;    // 构造函数。    // 输入参数包括"哈希值(h)", "键(k)", "值(v)", "下一节点(n)"    HashMapEntry(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;    }    // 判断两个Entry是否相等    // 若两个Entry的“key”和“value”都相等,则返回true。    // 否则,返回false    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;    }    // 实现hashCode()    public final int hashCode() {    return (key==null   ? 0 : key.hashCode()) ^    (value==null ? 0 : value.hashCode());    }    public final String toString() {    return getKey() + "=" + getValue();    }    // 当向HashMap中添加元素时,绘调用recordAccess()。    // 这里不做任何处理    void recordAccess(HashMap<K,V> m) {    }    // 当从HashMap中删除元素时,绘调用recordRemoval()。    // 这里不做任何处理    void recordRemoval(HashMap<K,V> m) {    }    }    // 新增Entry。将“key-value”插入指定位置,bucketIndex是位置索引。    void addEntry(int hash, K key, V value, int bucketIndex) {    /* java 原来的实现方法  保存“bucketIndex”位置的值到“e”中    Entry<K,V> e = table[bucketIndex];    // 设置“bucketIndex”位置的元素为“新Entry”,    // 设置“e”为“新Entry的下一个节点”    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);    // 若HashMap的实际大小 不小于 “阈值”,则调整HashMap的大小    if (size++ >= threshold)    resize(2 * table.length);    */ //按住实现方法if ((size >= threshold) && (null != table[bucketIndex])) {resize(2 * table.length);hash = (null != key) ? sun.misc.Hashing.singleWordWangJenkinsHash(key) : 0;bucketIndex = indexFor(hash, table.length);}}    // 创建Entry。将“key-value”插入指定位置。    void createEntry(int hash, K key, V value, int bucketIndex) {    // 保存“bucketIndex”位置的值到“e”中    HashMapEntry<K,V> e = table[bucketIndex];    // 设置“bucketIndex”位置的元素为“新Entry”,    // 设置“e”为“新Entry的下一个节点”    table[bucketIndex] = new HashMapEntry<K,V>(hash, key, value, e);    size++;    }    // HashIterator是HashMap迭代器的抽象出来的父类,实现了公共了函数。    // 它包含“key迭代器(KeyIterator)”、“Value迭代器(ValueIterator)”和“Entry迭代器(EntryIterator)”3个子类。    private abstract class HashIterator<E> implements Iterator<E> {    // 下一个元素    HashMapEntry<K,V> next;    // expectedModCount用于实现fast-fail机制。    int expectedModCount;    // 当前索引    int index;    // 当前元素    HashMapEntry<K,V> current;    HashIterator() {    expectedModCount = modCount;    if (size > 0) { // advance to first entry    HashMapEntry[] t = table;    // 将next指向table中第一个不为null的元素。    // 这里利用了index的初始值为0,从0开始依次向后遍历,直到找到不为null的元素就退出循环。    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();    // 注意!!!    // 一个Entry就是一个单向链表    // 若该Entry的下一个节点不为空,就将next指向下一个节点;    // 否则,将next指向下一个链表(也是下一个Entry)的不为null的节点。    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;    }    }    // value的迭代器    private final class ValueIterator extends HashIterator<V> {    public V next() {    return nextEntry().value;    }    }    // key的迭代器    private final class KeyIterator extends HashIterator<K> {    public K next() {    return nextEntry().getKey();    }    }    // Entry的迭代器    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {    public Map.Entry<K,V> next() {    return nextEntry();    }    }    // 返回一个“key迭代器”    Iterator<K> newKeyIterator()   {    return new KeyIterator();    }    // 返回一个“value迭代器”    Iterator<V> newValueIterator()   {    return new ValueIterator();    }    // 返回一个“entry迭代器”    Iterator<Map.Entry<K,V>> newEntryIterator()   {    return new EntryIterator();    }    // HashMap的Entry对应的集合    private transient Set<Map.Entry<K,V>> entrySet = null;    // 返回“key的集合”,实际上返回一个“KeySet对象”    public Set<K> keySet() {    Set<K> ks = keySet;    return (ks != null ? ks : (keySet = new KeySet()));    }    // Key对应的集合    // KeySet继承于AbstractSet,说明该集合中没有重复的Key。    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();    }    }    // 返回“value集合”,实际上返回的是一个Values对象    public Collection<V> values() {    Collection<V> vs = values;    return (vs != null ? vs : (values = new Values()));    }    // “value集合”    // Values继承于AbstractCollection,不同于“KeySet继承于AbstractSet”,    // Values中的元素能够重复。因为不同的key可以指向相同的value。    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();    }    }    // 返回“HashMap的Entry集合”    public Set<Map.Entry<K,V>> entrySet() {    return entrySet0();    }    // 返回“HashMap的Entry集合”,它实际是返回一个EntrySet对象    private Set<Map.Entry<K,V>> entrySet0() {    Set<Map.Entry<K,V>> es = entrySet;    return es != null ? es : (entrySet = new EntrySet());    }    // EntrySet对应的集合    // EntrySet继承于AbstractSet,说明该集合中没有重复的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();    }    }    // java.io.Serializable的写入函数    // 将HashMap的“总的容量,实际容量,所有的Entry”都写入到输出流中    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;    // java.io.Serializable的读取函数:根据写入方式读出    // 将HashMap的“总的容量,实际容量,所有的Entry”依次读出    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);    }    }    // 返回“HashMap总的容量”    int   capacity()     { return table.length; }    // 返回“HashMap的加载因子”    float loadFactor()   { return loadFactor;   }
}   /*************JDK8新增 放在底部********************/
/**
*Spliterator是Java 8引入的新接口,顾名思义,Spliterator可以理解为Iterator的Split版本
*(但用途要丰富很多)。使用Iterator的时候,我们可以顺序地遍历容器中的元素,使用*Spliterator的时候,我们可以将元素分割成多份,分别交于不于的线程去遍历,以提高效率。使用 *Spliterator 每次可以处理某个元素集合中的一个元素 — 不是从 Spliterator 中获取元素,而是 *使用 tryAdvance() 或 forEachRemaining() 方法对元素应用操作。但 Spliterator 还可以用 *于估计其中保存的元素数量,而且还可以像细胞分裂一样变为一分为二。这些新增加的能力让流并行处 *理代码*可以很方便地将工作分布到多个可用线程上完成。
*/// spliteratorsstatic class HashMapSpliterator<K,V> {final HashMap<K,V> map;HashMapEntry<K,V> current;  // current entryint index;                  // current index, modified on advance/splitint fence;                  // one past last indexint est;                    // size estimateint expectedModCount;       // for comodification checksHashMapSpliterator(HashMap<K,V> m, int origin,int fence, int est,int expectedModCount) {this.map = m;this.index = origin;this.fence = fence;this.est = est;this.expectedModCount = expectedModCount;}final int getFence() { // initialize fence and size on first useint hi;if ((hi = fence) < 0) {HashMap<K,V> m = map;est = m.size;expectedModCount = m.modCount;HashMapEntry<K,V>[] tab = m.table;hi = fence = (tab == null) ? 0 : tab.length;}return hi;}public final long estimateSize() {getFence(); // force initreturn (long) est;}}static final class KeySpliterator<K,V>extends HashMapSpliterator<K,V>implements Spliterator<K> {KeySpliterator(HashMap<K,V> m, int origin, int fence, int est,int expectedModCount) {super(m, origin, fence, est, expectedModCount);}public KeySpliterator<K,V> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid || current != null) ? null :new KeySpliterator<>(map, lo, index = mid, est >>>= 1,expectedModCount);}public void forEachRemaining(Consumer<? super K> action) {int i, hi, mc;if (action == null)throw new NullPointerException();HashMap<K,V> m = map;HashMapEntry<K,V>[] tab = m.table;if ((hi = fence) < 0) {mc = expectedModCount = m.modCount;hi = fence = (tab == null) ? 0 : tab.length;}elsemc = expectedModCount;if (tab != null && tab.length >= hi &&(i = index) >= 0 && (i < (index = hi) || current != null)) {HashMapEntry<K,V> p = current;current = null;do {if (p == null)p = tab[i++];else {action.accept(p.key);p = p.next;}} while (p != null || i < hi);if (m.modCount != mc)throw new ConcurrentModificationException();}}public boolean tryAdvance(Consumer<? super K> action) {int hi;if (action == null)throw new NullPointerException();HashMapEntry<K,V>[] tab = map.table;if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {while (current != null || index < hi) {if (current == null)current = tab[index++];else {K k = current.key;current = current.next;action.accept(k);if (map.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}}}return false;}public int characteristics() {return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |Spliterator.DISTINCT |((map instanceof LinkedHashMap) ? Spliterator.ORDERED : 0);}}static final class ValueSpliterator<K,V>extends HashMapSpliterator<K,V>implements Spliterator<V> {ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est,int expectedModCount) {super(m, origin, fence, est, expectedModCount);}public ValueSpliterator<K,V> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid || current != null) ? null :new ValueSpliterator<>(map, lo, index = mid, est >>>= 1,expectedModCount);}public void forEachRemaining(Consumer<? super V> action) {int i, hi, mc;if (action == null)throw new NullPointerException();HashMap<K,V> m = map;HashMapEntry<K,V>[] tab = m.table;if ((hi = fence) < 0) {mc = expectedModCount = m.modCount;hi = fence = (tab == null) ? 0 : tab.length;}elsemc = expectedModCount;if (tab != null && tab.length >= hi &&(i = index) >= 0 && (i < (index = hi) || current != null)) {HashMapEntry<K,V> p = current;current = null;do {if (p == null)p = tab[i++];else {action.accept(p.value);p = p.next;}} while (p != null || i < hi);if (m.modCount != mc)throw new ConcurrentModificationException();}}public boolean tryAdvance(Consumer<? super V> action) {int hi;if (action == null)throw new NullPointerException();HashMapEntry<K,V>[] tab = map.table;if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {while (current != null || index < hi) {if (current == null)current = tab[index++];else {V v = current.value;current = current.next;action.accept(v);if (map.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}}}return false;}public int characteristics() {return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |((map instanceof LinkedHashMap) ? Spliterator.ORDERED : 0);}}static final class EntrySpliterator<K,V>extends HashMapSpliterator<K,V>implements Spliterator<Map.Entry<K,V>> {EntrySpliterator(HashMap<K,V> m, int origin, int fence, int est,int expectedModCount) {super(m, origin, fence, est, expectedModCount);}public EntrySpliterator<K,V> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid || current != null) ? null :new EntrySpliterator<>(map, lo, index = mid, est >>>= 1,expectedModCount);}public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {int i, hi, mc;if (action == null)throw new NullPointerException();HashMap<K,V> m = map;HashMapEntry<K,V>[] tab = m.table;if ((hi = fence) < 0) {mc = expectedModCount = m.modCount;hi = fence = (tab == null) ? 0 : tab.length;}elsemc = expectedModCount;if (tab != null && tab.length >= hi &&(i = index) >= 0 && (i < (index = hi) || current != null)) {HashMapEntry<K,V> p = current;current = null;do {if (p == null)p = tab[i++];else {action.accept(p);p = p.next;}} while (p != null || i < hi);if (m.modCount != mc)throw new ConcurrentModificationException();}}public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {int hi;if (action == null)throw new NullPointerException();HashMapEntry<K,V>[] tab = map.table;if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {while (current != null || index < hi) {if (current == null)current = tab[index++];else {HashMapEntry<K,V> e = current;current = current.next;action.accept(e);if (map.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}}}return false;}public int characteristics() {return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |Spliterator.DISTINCT |((map instanceof LinkedHashMap) ? Spliterator.ORDERED : 0);}}// Subclass overrides these to alter behavior of views' iterator() methodIterator<K> newKeyIterator()   {return new KeyIterator();}Iterator<V> newValueIterator()   {return new ValueIterator();}Iterator<Map.Entry<K,V>> newEntryIterator()   {return new EntryIterator();}

HashMap源码深入解析相关推荐

  1. HashMap源码深度解析【重点】

    [重点]HashMap源码深度解析 摘要 哈希表 哈希冲突 HashMap 数据结构 数据结构 HashMap实现原理 构造方法 PUT实现 HashMap的数组长度一定是2的次幂 get原理 Has ...

  2. HashMap源码解析(JDK1.8)

    HashMap源码解析(JDK1.8) 目录 定义 构造函数 数据结构 存储实现源码分析 删除操作源码分析 hashMap遍历和异常解析 1. 定义 HashMap实现了Map接口,继承Abstrac ...

  3. 面试官系统精讲Java源码及大厂真题 - 08 HashMap 源码解析

    08 HashMap 源码解析 自信和希望是青年的特权. --大仲马 引导语 HashMap 源码很长,面试的问题也非常多,但这些面试问题,基本都是从源码中衍生出来的,所以我们只需要弄清楚其底层实现原 ...

  4. Java集合框架之三:HashMap源码解析

    Java集合框架之三:HashMap源码解析 版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集 ...

  5. hashmap删除指定key_Java集合之HashMap源码解析(JDK8)

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景非常丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...

  6. 万字长文|Hashtable源码深度解析以及与HashMap的区别

    基于JDK1.8对Java中的Hashtable集合的源码进行了深度解析,包括各种方法.扩容机制.哈希算法.遍历方法等方法的底层实现,最后给出了Hashtable和HashMap的详细对比以及使用建议 ...

  7. 通俗易懂Hashmap源码解析

    Hashmap源码解析 一.Hashmap数据结构 哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value.哈希的思路很简单 ...

  8. 红黑树分析与JDK8中HashMap源码解析

    红黑树分析与JDK8中HashMap源码解析 BST O(1), O(n), O(logn), O(nlogn) 的区别 红黑树-RBTree 插入数据 HashMap中红黑树的插入操作 HashMa ...

  9. 【Java深入研究】9、HashMap源码解析(jdk 1.8)

    一.HashMap概述 HashMap是常用的Java集合之一,是基于哈希表的Map接口的实现.与HashTable主要区别为不支持同步和允许null作为key和value.由于HashMap不是线程 ...

最新文章

  1. 20年的人工智能设计总结:向产品中注入人工智能的指南
  2. Effective C++ Item 30 inline里里外外
  3. as点击发送广播_Apache Flink 中广播状态的实用指南
  4. boost::mp11::mp_set_union相关用法的测试程序
  5. perl大骆驼和小骆驼_从代码内部:骆驼路由引擎第一部分
  6. 《ArcGIS Runtime SDK for Android开发笔记》——(1)、Android Studio下载与安装
  7. VMware16虚拟机怎么共享文件夹?
  8. html网页打不开二级网页,二级网页打不开,小编教你浏览器二级页面打不开怎么解决...
  9. Entity Framework 异常档案
  10. MySQL之Got fatal error 1236 from master when reading data from binary log
  11. JS的浅拷贝和深拷贝
  12. matlab液体湿润模拟,【水文模型】01 三水源新安江模型
  13. Android修行手册-EditText属性以及光标和小键盘控制
  14. html图片自动适应屏幕代码,css让图片宽度自适应屏幕的例子
  15. 上传文件nginx限制大小解决
  16. java动物继承_java 编码实现动物世界的继承关系:动物(Animal)属性:名称(name)具有行为:吃(eat)、睡觉(sleep)...
  17. json vs jsonb,及常用
  18. Flume下读取kafka数据后再打把数据输出到kafka,利用拦截器解决topic覆盖问题
  19. esxi改mac地址_ESXI克隆CentOS修改MAC地址
  20. hint: Updates were rejected because the tip of your current branch is behind(git push线上与本地版本冲突问题)

热门文章

  1. Centos之数据库基础
  2. vue+Element实现静态旅游网站
  3. slf4j使用日志文件配置
  4. CMMI—组织级绩效管理
  5. filter与ifilter
  6. 接口自动化 ------ 快速搭建接口自动化框架
  7. UART串口的H4协议和H5协议
  8. 学习HTML(十五)——结合CSS文件在页中创建按钮
  9. Netty异步非阻塞事件驱动及组件原理详解
  10. bt_code(2012.3.17)