莱莱 发表于 2023-12-2 12:41:02

HashMap源码详解

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个初始化方法,分别是:
    public HashMap(int initialCapacity, float loadFactor) {      if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal initial capacity: " +                                             initialCapacity);      // MAXIMUM_CAPACITY = 1MAXIMUM_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
页: [1]
查看完整版本: HashMap源码详解