java中常用到HashMap,决定了解其实现原理。
1、存储结构
1.1、数组
存储空间连续,空间复杂度大,但查询时时间复杂度小,为O(1)。即寻址容易,插入、删除困难。
1.2、链表
存储空间可以不连续,空间复杂度小,但查询时间复杂度大,为O(n)。即插入、删除容易,寻址困难。
1.3、哈希表
将数组和链表结合,取长补短,产生一种寻址容易,插入删除也容易的数据结构。
在HashMap中有静态内部类Entry,主要结构是key、value和next,形成一个链表结构。在HashMap中有定义 transient Entry[] table来存储Entry。这样HashMap用线性数组来存储数据,根据hash值来创建Entry链。
2、存取原理
2.1、put
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode());//计算用来计算存储位置的值 int i = indexFor(hash, table.length);//计算存储位置的下标 for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {//key相同时替换原来的value V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++;//结构改变次数,与fail-fast机制有关 addEntry(hash, key, value, i);//构造Entry并存储 return null; }
void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex];//取出原来存储在bucketIndex位置的Entry e table[bucketIndex] = new Entry<K,V>(hash, key, value, e);//创建新的Entry,并将next设置为e if (size++ >= threshold)//当前数量达到需要扩容的门槛 resize(2 * table.length);//重新计算容量 }
2.2、get
public V get(Object key) { if (key == null) return getForNullKey(); int hash = hash(key.hashCode());//计算用来计算存储位置的值 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {//获取目标Entry的位置Entry链,并遍历改Entry链查找目标Entry Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value;//找到目标返回 } return null; }
2.3、remove
public V remove(Object key) { Entry<K,V> e = removeEntryForKey(key);//删除对应的Entry return (e == null ? null : e.value);//返回对应Entry的Value } final Entry<K,V> removeEntryForKey(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length); Entry<K,V> prev = table[i];//找到对应Entry的存储链上的第一Entry Entry<K,V> e = prev;//e表示当前Entry while (e != null) { Entry<K,V> next = e.next;//找到e的下一个Entry标记为next Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {//发现e是要删除的Entry modCount++;//标记结构改变次数 size--;//容量减一 if (prev == e)//e是前一个Entry table[i] = next; else prev.next = next;//前一个Entry的next设为next e.recordRemoval(this); return e;//返回被删除的Entry } prev = e;//当前的Entry变成前一个Entry e = next;//下一个Entry变成当前的,继续判断e是否是要被删除的Entry } return e; }
3、rehash过程
void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) {//原数组容量已达到可用容量的上限 threshold = Integer.MAX_VALUE;//阈值设为最大的int return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable);//将原来的数组中的内容重新计算放在新的数组 table = newTable; threshold = (int)(newCapacity * loadFactor);//重新设置阈值,loadFactor默认是0.75,一般不需要改变 } void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K,V> e = src[j]; if (e != null) { src[j] = null; do { Entry<K,V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } }
所以,如果事先知道要存储数量的大小,可预先设置好容器的大小(默认是16),减少resize的调用,以提高速度。
相关推荐
在深入探讨HashMap的实现原理之前,我们需要了解两个关键的接口方法:`hashCode()`和`equals()`。 根据《Effective JAVA》的建议,当重写`equals()`方法时,也应重写`hashCode()`方法。这是因为在HashMap中,`...
"基于HashMap的用户标签处理兼Java中HashMap实现原理研究" 本文研究了基于HashMap的用户标签处理方法,并对Java中HashMap的实现原理进行了深入研究。HashMap是一种高效的数据结构,可以快速地存储和检索数据。本文...
Java HashMap原理分析 Java HashMap是一种基于哈希表的数据结构,它的存储原理是通过将Key-Value对存储在一个数组中,每个数组元素是一个链表,链表中的每个元素是一个Entry对象,Entry对象包含了Key、Value和指向...
Java8之后新增挺多新东西,接下来通过本文给大家介绍Java8 HashMap的实现原理分析,对java8 hashmap实现原理相关知识感兴趣的朋友一起学习吧
### HashMap的实现原理 #### 1. HashMap概述 HashMap 是 Java 集合框架中一个非常重要的类,它实现了 Map 接口,并提供了基于哈希表的存储方式。与其它 Map 实现不同的是,HashMap 允许使用 `null` 键和 `null` 值...
综上所述,理解HashMap的实现原理对于优化Java程序性能至关重要,尤其是在处理大量数据或并发场景时。在实际应用中,应根据具体需求选择合适的数据结构,例如,如果需要线程安全,可以选择ConcurrentHashMap;如果对...
一线大厂BATJ面试题讲解-hashmap原理实现
根据提供的文件信息,以下是对JDK 8.0中HashMap实现原理的详细知识点介绍: 1. HashMap概述 HashMap是Java集合框架的一部分,它实现了Map接口,用于存储键值对。其核心特点在于基于哈希表的映射机制,能够通过键...
以下是对HashMap实现原理的详细解析。 首先,HashMap内部使用了一个瞬时变量数组`table`(也称为“桶”)来存储键值对。桶是一个Entry对象数组,它的大小可以动态调整,并且长度必须是2的幂。初始时,`table`是一个...
在这个系统中,使用HashMap实现是一种高效且灵活的方法,因为HashMap提供了快速的查找和插入操作。本文将深入探讨如何使用HashMap来构建一个电话本管理系统,并通过源码分析增强理解。 HashMap是Java集合框架中的一...
### JDK 7.0集合系列解析之HashMap实现原理 #### 一、HashMap概述 HashMap是Java集合框架中Map接口的典型实现之一,主要用于存储键值对(Key-Value)数据。其特性如下: - 线程不安全,方法为非同步方法,因此多...
"学习笔记:三数组实现的HashMap"这篇博客文章可能讨论了一种非标准但有趣的HashMap实现,使用了三个数组来代替标准的哈希表结构。这里我们将深入探讨这种三数组实现HashMap的原理和可能的优势。 1. **基本概念**:...
本文将深入解析HashMap的工作原理、内部结构以及相关操作。 首先,哈希表是一种数据结构,它通过哈希函数将键(Key)映射到数组的索引位置,从而实现快速访问。HashMap在Java中是线程非同步的,适用于多线程环境下...
答:在多线程环境下,可以使用ConcurrentHashMap,它是线程安全的HashMap实现。 五、HashMap与HashSet的关系 HashSet基于HashMap实现,每个元素作为HashMap的一个键,值为null。因此,HashSet的操作性能也依赖于...
HashMap的实现原理基于哈希表,它的核心是通过哈希函数将键(key)映射到一个数组的特定位置,从而实现快速访问。本文将深入解析HashMap的put和get操作的内部机制。 首先,HashMap的底层数据结构是一个动态扩容的...
面试中,HashMap的源码分析与实现是一个常见的考察点,因为它涉及到数据结构、并发处理和性能优化等多个核心领域。本篇文章将深入探讨HashMap的内部工作原理、关键特性以及其在实际应用中的考量因素。 HashMap基于...
HashMap类在Java编程...在阅读《HashMap1.js》和《HashMap.js》这两个文件时,可以深入分析其JavaScript版本的HashMap实现,虽然与Java版本可能有所不同,但基本的哈希映射原理是相通的,有助于拓宽对哈希表的理解。
HashMap 的核心原理是将键(key)通过哈希函数转化为数组索引,然后将键值对(key-value pair)存储在数组的对应位置。如果多个键经过哈希计算得到相同的索引,HashMap 利用链表处理这种哈希冲突,形成链式存储。 ...