HashMap优点总结及源码分析

HashMap优点总结:

  1. 可存储不同类型的数据:使用泛型来定义键和值的类型,兼容所有数据类型
  2. 高效的查找和插入操作:通过key的hash映射,实现快速的查找和插入操作。时间复杂度基本为O(1)
  3. 灵活的容量调整:可根据数据量增长自行动态扩容。当容量过大时,HashMap会自动进行缩容,从而提高空间利用率
  4. 节点转换:当链表中的节点个数超过8个时,结构会转换为红黑树,以减少平均查找时间,提高插入和删除操作的性能。
  5. 可存储大量数据:HashMap的存储空间只受限于计算机的内存大小。
  6. 支持快速迭代:HashMap提供了快速的迭代方法,可以方便地遍历所有的键值对。
  7. 优秀的算法1:表容量保证是2的幂数,容量-1做与运算的散列效果更好,同时便于计算扩容后元素位置,可以提高扩容效率
  8. 优秀的算法2:高效的容量值优化算法,借用位运算高效运算。输入容量-1,之后将后面的每一个二进制位都转为1,最后值+1,保证最终结果一定是大于等于当前值的最小2的幂
  9. 优秀的算法3:key的hash运算,key的hashcode值向右位运算,纳入高位影响,更好的实现扩散效果,同时减少hash碰撞
  10. 迭代器快速失败:HashMap的迭代器使用快速失败机制,通过modCount属性监测并发修改,即在迭代时如果有其他线程并发地修改了HashMap的结构(例如添加或删除键值对),那么迭代器会立即抛出ConcurrentModificationException异常,避免出现数据不一致的情况。

好的设计思想:根据不同数据量,灵活切换多样合适的数据结构,如Redis的数据结构中也有体现

源码解析:

HashMap类

public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {

泛型容纳所有类型的key,value包括null

属性解析

/*** 版本序列号,可保证当类增减属性后,依旧可以反序列化成功* 位运算,提醒大家hash表大小一定是2的幂*/
private static final long serialVersionUID = 362498820763181265L;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16/*** 总数量,默认最大容量;最大容量一定是2的幂数* 好处1:2的幂值-1做与运算散列效果更好* 好处2:便于计算扩容后元素位置可以提高扩容效率*/
static final int MAXIMUM_CAPACITY = 1 << 30;/*** 构造方法不指定时的默认负载因子* 达到总容量的75% 即resize扩容*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;/*** 链表长度至少达到8 结构才能转为红黑树*/
static final int TREEIFY_THRESHOLD = 8;/*** 树的节点数减到6 退化为链表*/
static final int UNTREEIFY_THRESHOLD = 6;/*** 数组的长度至少达到64,链表才能转为红黑树*/
static final int MIN_TREEIFY_CAPACITY = 64;

Node解析

Node存储实际key,value数据的结构,TreeNode的父类

    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;}public final K getKey()        { return key; }public final V getValue()      { return value; }public final String toString() { return key + "=" + value; }public final int hashCode() {return Objects.hashCode(key) ^ Objects.hashCode(value);}public final V setValue(V newValue) {V oldValue = value;value = newValue;return oldValue;}public final boolean equals(Object o) {if (o == this)return true;if (o instanceof Map.Entry) {Map.Entry<?,?> e = (Map.Entry<?,?>)o;if (Objects.equals(key, e.getKey()) &&Objects.equals(value, e.getValue()))return true;}return false;}}

key的hash计算方式解析

    static final int hash(Object key) {int h;// 向右位运算,纳入高位影响,更好的实现扩散效果,同时减少hash碰撞,^运算结果不同为1相同为0return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

tableSizeFor表扩容容量值优化方法解析

为保证key更好的分散效果及更佳的扩容效率,保证最大容量始终是2的幂

	/*** 将输入容量规范化为2的幂          			       * 算法逻辑:位运算效率更高。输入容量-1,之后将后面的每一个二进制位都转为1,最后值+1,保证最终结果一定是大于等于当前值的最小2的幂	*/static final int tableSizeFor(int cap) {int n = cap - 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}

Fields 其他属性解析

 /* ---------------- Fields -------------- *//*** The table, initialized on first use, and resized as* necessary. When allocated, length is always a power of two.* (We also tolerate length zero in some operations to allow* bootstrapping mechanics that are currently not needed.)* transient 修饰,序列化会忽略此属性*/transient Node<K,V>[] table;/*** Holds cached entrySet(). Note that AbstractMap fields are used* for keySet() and values().*/transient Set<Map.Entry<K,V>> entrySet;/*** The number of key-value mappings contained in this map.*/transient int size;/*** The number of times this HashMap has been structurally modified* Structural modifications are those that change the number of mappings in* the HashMap or otherwise modify its internal structure (e.g.,* rehash).  This field is used to make iterators on Collection-views of* the HashMap fail-fast.  (See ConcurrentModificationException).* 在HashMap中用于记录结构修改次数,以支持Fail-Fast机制并防止并发修改导致的不一致操作。*/transient int modCount;/*** The next size value at which to resize (capacity * load factor).** @serial*/// (The javadoc description is true upon serialization.// Additionally, if the table array has not been allocated, this// field holds the initial array capacity, or zero signifying// DEFAULT_INITIAL_CAPACITY.)int threshold;/*** The load factor for the hash table.** @serial*/final float loadFactor;

put方法解析

第一次初始化hash表是在第一次调用put的时候

插入,更新,获取都是大体思路相同

  1. 判断表是否为null或长度length=0
  2. 定位到hash桶中key的位置
  3. 判断头结点是否存在并进行处理
  4. 判断为树结构并进行处理
  5. 判断为链表结构并进行处理
/*** Associates the specified value with the specified key in this map.* If the map previously contained a mapping for the key, the old* value is replaced.** @param key key with which the specified value is to be associated* @param value value to be associated with the specified key* @return the previous value associated with <tt>key</tt>, or*         <tt>null</tt> if there was no mapping for <tt>key</tt>.*         (A <tt>null</tt> return can also indicate that the map*         previously associated <tt>null</tt> with <tt>key</tt>.)*/public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}/*** Implements Map.put and related methods** @param hash hash for key* @param key the key* @param value the value to put* @param onlyIfAbsent if true, don't change existing value* @param evict if false, the table is in creation mode.* @return previous value, or null if none*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;// hash桶定位计算方法(n - 1) & hash。模运算也可以做到,但是没有位运算效率高if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/55635.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebSocked基础

一. WebSocket 基本概念 WebSocket是什么&#xff1f; WebSocket 是基于 TCP 的一种新的应用层网络协议。它提供了一个全双工的通道&#xff0c;允许服务器和客户端之间实时双向通信。因此&#xff0c;在 WebSocket 中&#xff0c;浏览器和服务器只需要完成一次握手&#xff…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于AGCN-LSTM模型的海上风电场功率概率预测 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

端到端自动驾驶模型SparseDrive部署过程

SparseDrive 论文链接 https://arxiv.org/pdf/2405.19620 仓库链接 https://github.com/swc-17/SparseDrive 论文和模型的相关介绍大家可以参考其他博客的介绍&#xff0c;这里只介绍模型部署的过程和中间可能遇到的问题解决办法&#xff0c;以及代码解析和使用记录。 模型部署…

解决ubuntu20 启动卡死在 installing open-vm-tools 问题

------------------------------------------------------------------------------- 1. 解决ubuntu20 启动卡死在 installing open-vm-tools 问题 ------------------------------------------------------------------------------- 最近VMware 安装ubuntu-20.04.6-desktop…

FLINK SQL时区问题

SQL时区问题 在Flink SQL中&#xff0c;时区问题是一个需要特别关注的点&#xff0c;因为时区的不一致可能会导致数据的不一致性。以下是对Flink SQL时区问题的详细解释和解决方案&#xff1a; 一、时区问题背景 时间类型与时区&#xff1a; 在Flink SQL中&#xff0c;时间类…

CyberRT通信介绍与基于Reader、Writer的通信实践(apollo9.0)

目录 数据通信场景 CyberRT中的通信方式 ​编辑 通信模式 话题通信 服务通信 参数通信 protobuf protobuf简介 protobuf文件编写 topic通信实验 实验环境 实验准备 代码编写 定义消息格式 发送消息 接收消息 定义编译规则 程序编译 运行程序 数据通信场景 …

fabric-sdk-go

Fabric-SDK-go 区块链网络搭建fabric-sdk代码代码结构&#xff1a;代码eg&#xff1a; 区块链网络搭建 使用fabric-sample的网络结构用容器搭建起测试网络即可。 fabric-sdk代码 代码很简易&#xff0c;主要为了了解怎么使用fabric为编程人员提供的sdk从而提供HTTP接口的情况…

Git 修改分支名

在Git中修改分支名称&#xff0c;可以使用以下步骤&#xff1a; 切换到要重命名分支之外的其他分支&#xff1a; git checkout <其他分支名>重命名本地分支&#xff1a; git branch -m <旧分支名> <新分支名>如果需要删除远程的旧分支并创建新分支&#xff1…

浅谈华为 HarmonyOS Next

1. 万物互联时代的新机遇 随着万物互联时代的到来&#xff0c;智能应用从几十亿部手机扩展到数百亿个IoT设备&#xff0c;深刻改变了人们的生活方式。这为我们应用开发者带来了新的机遇和挑战。 机遇 : 目前正处于万物互联时代的前夕&#xff0c;正在经历手机单设备到全场景多…

技术分享:A-23OH型树脂在汽车涂装废溶剂回收中的应用

在当今汽车制造业竞争激烈的环境下&#xff0c;提高生产效率、降低成本的同时&#xff0c;满足环保要求已成为各制造商追求的核心目标。水性涂料因其环保、节能等多重优势&#xff0c;在汽车涂装领域的应用日益广泛。然而&#xff0c;随之而来的喷涂废溶剂处理问题也日益凸显。…

从 Hadoop 迁移到数据 Lakehouse 的架构师指南

从 Hadoop 到数据湖仓一体架构的演变代表了数据基础架构的重大飞跃。虽然 Hadoop 曾经以其强大的批处理能力统治着大数据领域&#xff0c;但如今的组织正在寻求更敏捷、更具成本效益和现代化的解决方案。尤其是当他们越来越多地开始实施 AI 计划时。根本没有办法让 Hadoop 为 A…

计算机网络架构实例

小型企业网络 1. 终端设备&#xff1a; - 员工的台式电脑和笔记本电脑&#xff0c;用于日常办公&#xff0c;如文档处理、邮件收发、业务软件使用等。 - 智能手机和平板电脑&#xff0c;方便员工在外出或移动办公时也能接入公司网络&#xff0c;查看邮件和处理紧急事务。 2.…

三周精通FastAPI:1 第一步入门

FastAPI是一个非常棒的python web和api框架&#xff0c;准备用三周的时间“精通它” 学习流程参考FastAPI官网的用户教程&#xff1a;教程 - 用户指南 - FastAPI 学前提示 运行代码 所有代码片段都可以复制后直接使用&#xff08;它们实际上是经过测试的 Python 文件&#x…

UG NX12.0建模入门笔记:1.0 UG NX12.0安装教程

一、如何关闭防火墙&#xff1f; 提示&#xff1a;安装软件之前&#xff0c;建议先 关闭防火墙和杀毒软件&#xff01;&#xff01;&#xff01; 文章目录 一、如何关闭防火墙&#xff1f;二、UG NX12.0安装包三、UG NX12.0安装教程1.新建文件夹2.安装JAVA环境3.安装许可证管理…

LeetCode_2235. 两整数相加_java

1、问题 2235. 两整数相加https://leetcode.cn/problems/add-two-integers/ 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num1 12, num2 5 输出&#xff1a;17 解释&#xff1a;num1 是 12&#xff0c;num2 是 5 &am…

智慧监管:EasyCVR视频汇聚智能分析平台助力有限空间作业实现全天候可视化监控

随着工业化和城市化进程的加快&#xff0c;有限空间作业&#xff08;如地下管道、储罐、隧道等&#xff09;在各类企事业单位中日益频繁。然而&#xff0c;这类作业环境复杂、危险系数高&#xff0c;对作业人员的安全管理和实时监控提出了严峻挑战。为了保障有限空间作业的安全…

021_Thermal_Transient_in_Matlab统一偏微分框架之热传导问题

Matlab求解有限元专题系列 固体热传导方程 固体热传导的方程为&#xff1a; ρ C p ( ∂ T ∂ t u t r a n s ⋅ ∇ T ) ∇ ⋅ ( q q r ) − α T d S d t Q \rho C_p \left( \frac{\partial T}{\partial t} \mathbf{u}_{\mathtt{trans}} \cdot \nabla T \right) \nab…

开发一个微信小程序要多少钱?

在当今数字化时代&#xff0c;微信小程序成为众多企业和个人拓展业务、提供服务的热门选择。那么&#xff0c;开发一个微信小程序究竟需要多少钱呢&#xff1f; 开发成本主要取决于多个因素。首先是功能需求的复杂程度。如果只是一个简单的信息展示小程序&#xff0c;功能仅限…

Hadoop集群基础搭建

目录 一.虚拟机安装 1.配置虚拟机的ip 2.配置本机的ip 3.新建虚拟机 4.克隆三台虚拟机 二.虚拟机网络配置 1.修改ip配置 2.配置主机名和主机映射 3.配置SSH免密登陆 三.安装JDK 1.tar命令解压JDK安装包 2.配置JDK的环境变量 四.安装Hadoop 1.tar命令解压Hadoop安…

Maven项目打包为jar的几种方式

1.直接打包 通过不打依赖包的方式&#xff0c;仅仅只是打包出项目中的代码到JAR包中。在POM文件合适的位置添加如下plugin即可&#xff0c;随后执行maven install <plugin> <groupId>org.apache.maven.plugins</groupId> &l…