HashMap简介
HashMap是Java语言中的一种集合类,它实现了Map接口,用于存储Key-Value对。它基于哈希表数据结构,通过计算Key的哈希值来快速定位Value的位置,从而实现高效的插入、删除和查找操作。下面我们对照着JAVA1.8中的HashMap源码来分析一下它的内部实现逻辑
基本的结构
在开始分析HashMap的实现逻辑之前,我们需要先了解一下基础的组成和内部的成员变量都有哪些,分别代表什么意思。
1、Node
首先我们看一下HashMap其中一个子类:Node,这个子类用于存储基本的元素,即Key-Value对、Key的Hash值以及指向下一个节点的Node变量。在HashMap内部,由Node类型组成的数组用来存储所有的元素。 Node实现自Map.Entry接口,并且实现了接口中规定的多个基本方法:- interface Entry<K,V> {
- K getKey();
- V getValue();
- V setValue(V value);
- boolean equals(Object o);
- int hashCode();
- ...
- }
复制代码 同时,在Node类中,定义了4个成员变量:- public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>,Cloneable,Serializable {
- ....
- static class Node<K,V> implements Map.Entry<K,V> {
- final int hash;
- final K key;
- V value;
- Node<K,V> next;
- Node(int hash, K key, V value, Node<K,V> next) {
- this.hash = hash;
- this.key = key;
- this.value = value;
- this.next = next;
- }
- ...
- }
- ...
- }
复制代码 其中hash是key的hash值,key和value存储键和值,next变量指向链表中的下一个元素。
2、HashMap的成员变量
- transient Node<K,V>[] table;
- transient Set<Map.Entry<K,V>> entrySet;
- transient int size;
- transient int modCount;
- int threshold;
- final float loadFactor;
复制代码 table:保存所有元素的数组。
entrySet:一个用于遍历所有数据节点的集合。
size:记录HashMap中元素的总数量。
modCount:用来判断在对HashMap数据项进行遍历时,其中的数据项是否有修改过,如删除或者新增一项。
threshold:控制扩容时机,当数据项数量大于threshold时进行扩容,新的容量大小是老的两倍。
loadFactor:默认值0.75,加载因子决定threshold大小,计算公式是threshold=table.length*loadFactor。
我们先大致了解一下HashMap成员变量及基础的Key-Value承载的结构,之后随着介绍的进度我们再介绍新的类型。下面我们开始正式分析HashMap的逻辑。
初始化方法
HashMap有4个初始化方法,分别是:
[code] public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); // MAXIMUM_CAPACITY = 1 MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor ) o; Object key = e.getKey(); Node candidate = getNode(hash(key), key); return candidate != null && candidate.equals(e); } public final boolean remove(Object o) { if (o instanceof Map.Entry) { Map.Entry e = (Map.Entry) o; Object key = e.getKey(); Object value = e.getValue(); return removeNode(hash(key), key, value, true, true) != null; } return false; } public final Spliterator spliterator() { return new EntrySpliterator(HashMap.this, 0, -1, 0, 0); } /** * 遍历方法对所有元素进行遍历时,会判断modCount是否有变化,如果有变,说明在遍历途中,有其他线程对元素进行了增加或者删除, * 有线程安全问题所以抛出异常。或者在遍历方法内对集合元素进行了增加或删除操作。 */ public final void forEach(Consumer |