HashMap源码详解

莱莱  金牌会员 | 2023-12-2 12:41:02 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 902|帖子 902|积分 2706

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接口,并且实现了接口中规定的多个基本方法:
  1.     interface Entry<K,V> {
  2.         K getKey();
  3.         V getValue();
  4.         V setValue(V value);
  5.         boolean equals(Object o);
  6.         int hashCode();
  7.         ...
  8.     }
复制代码
同时,在Node类中,定义了4个成员变量:
  1. public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>,Cloneable,Serializable {
  2.     ....
  3.     static class Node<K,V> implements Map.Entry<K,V> {
  4.             final int hash;
  5.             final K key;
  6.             V value;
  7.             Node<K,V> next;
  8.             Node(int hash, K key, V value, Node<K,V> next) {
  9.                 this.hash = hash;
  10.                 this.key = key;
  11.                 this.value = value;
  12.                 this.next = next;
  13.             }
  14.             ...
  15.     }
  16.     ...
  17. }
复制代码
其中hash是key的hash值,key和value存储键和值,next变量指向链表中的下一个元素。
2、HashMap的成员变量
  1.     transient Node<K,V>[] table;
  2.     transient Set<Map.Entry<K,V>> entrySet;
  3.     transient int size;
  4.     transient int modCount;
  5.     int threshold;
  6.     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
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莱莱

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表