Java中HashMap的基本介绍和详细讲解,HashMap的遍历以及HashMap的底层源码的分析

HashMap 基本介绍

HashMap 是 Java 中的一个集合类,实现了 Map 接口用于存储键值对(key-value)数据。它基于哈希表的数据结构实现,可以实现高效的查找、插入和删除操作。

HashMap 细节讨论

  1. 无序性: HashMap 中的元素是无序的,即遍历的顺序不一定是元素插入的顺序。
  2. 键唯一性: HashMap键是唯一的,不允许重复的键。如果插入相同的键,后面的值会覆盖前面的值
  3. 允许 null 键和 null 值: HashMap 允许使用 null 作为键并且允许键对应的值为 null,但是只允许有一个null键,因为键是唯一的。
  4. 非线程安全: HashMap 不是线程安全的,如果多个线程同时访问并修改同一个 HashMap,可能会导致数据不一致或其他错误。
  5. 初始容量和负载因子: HashMap 允许设置初始容量和负载因子,初始容量是哈希表中桶的数量,负载因子是哈希表在达到多满时进行扩容操作(这里和HashSet一样,因为HashSet的底层是用HashMap实现的)。

使用注意事项

  1. 线程安全性: 如果需要在多线程环境中使用 HashMap,需要进行适当的同步处理,或者考虑使用线程安全的集合类(如 ConcurrentHashMap)。
  2. 哈希冲突: 当不同的键映射到相同的哈希值时,发生哈希冲突。HashMap 使用链表(JDK8 之前)或红黑树(JDK8 及以后)来处理哈希冲突。
  3. equals 和 hashCode 方法: 在使用自定义类作为 HashMap 的键时,需要正确实现该类的 equalshashCode 方法,以确保键的唯一性和正确的哈希计算。

常用方法

以下是一些常用的 HashMap 方法:

  • put(key, value): 向 HashMap 中插入键值对。
  • get(key): 根据键获取对应的值。
  • containsKey(key): 判断是否包含指定键。
  • containsValue(value): 判断是否包含指定值。
  • remove(key): 根据键删除对应的键值对。
  • size(): 返回 HashMap 中键值对的数量。
  • isEmpty(): 判断 HashMap 是否为空。
  • keySet(): 返回包含所有键的集合。
  • values(): 返回包含所有值的集合。
  • entrySet(): 返回包含所有键值对的集合。

底层源码和底层实现

HashMap 的底层实现主要是基于哈希表,其中每个桶(bucket)是一个链表或红黑树。当哈希冲突发生时,新的键值对会被插入到相应的桶中。

HashMap 的底层源码非常复杂,涉及哈希计算、扩容、桶的处理等多个方面。如果想深入了解 HashMap 的底层实现,可以查阅 Java 的源代码或相关的学习资料。

在这里插入图片描述
HashMap的遍历代码:

public class HashMap_ {public static void main(String[] args) {HashMap hashMap = new HashMap();hashMap.put(1,new Student("1","ret1",23,"计算机"));hashMap.put(2,new Student("2","ret2",23,"计算机"));hashMap.put(3,new Student("3","ret3",23,"计算机"));System.out.println(hashMap);for (Object entry : hashMap.entrySet()) {Map.Entry entry1 = (Map.Entry) entry;System.out.println(entry1.getKey()+"        "+entry1.getValue());}Set set = hashMap.keySet();for (Object key :set) {System.out.println(key+"    "+hashMap.get(key));}}
}class Student{private String sno;private String name;private int age;private String major;public Student(String sno, String name, int age, String major) {this.sno = sno;this.name = name;this.age = age;this.major = major;}public String getSno() {return sno;}public void setSno(String sno) {this.sno = sno;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getMajor() {return major;}public void setMajor(String major) {this.major = major;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(sno, student.sno) && Objects.equals(name, student.name) && Objects.equals(major, student.major);}@Overridepublic int hashCode() {return Objects.hash(sno, name, age, major);}@Overridepublic String toString() {return "Student{" +"sno='" + sno + '\'' +", name='" + name + '\'' +", age=" + age +", major='" + major + '\'' +'}';}
}

HashMap的底层代码:

/*HashMap底层原理1. 执行构造器 new HashMap()初始化加载因子 loadFactor = 0.75HashMap$Node[] table = null2. 执行 put 调用 hash 方法,计算 key 的 hash 值(h = key.hashCode()) ^ (h >>> 16)public V put (K key, V value){//K = "java" value = 10return putVal(hash(key), key, value, false, true);}3. 执行 putValfinal V putVal ( int hash, K key, V value,boolean onlyIfAbsent, boolean evict){Node<K, V>[] tab;Node<K, V> p;int n, i;//辅助变量//如果底层的 table 数组为 null, 或者 length =0 , 就扩容到 16if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//取出 hash 值对应的 table 的索引位置的 Node, 如果为 null, 就直接把加入的 k-v创建成一个 Node ,加入该位置即可if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K, V> e;K k;//辅助变量// 如果 table 的索引位置的 key 的 hash 相同和新的 key 的 hash 值相同,// 并满足(table 现有的结点的 key 和准备添加的 key 是同一个对象 || equals 返回真)就认为不能加入新的 k-vif (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)//如果当前的 table 的已有的 Node 是红黑树,就按照红黑树的方式处理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);//加入后,判断当前链表的个数,是否已经到 8 个,到 8 个,后//就调用 treeifyBin 方法进行红黑树的转换if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash && //如果在循环比较过程中,发现有相同,就 break,就只是替换 value((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; //替换,key 对应 valueafterNodeAccess(e);return oldValue;}}++modCount;//每增加一个 Node ,就 size++if (++size > threshold[12 - 24 - 48])//如 size > 临界值,就扩容resize();afterNodeInsertion(evict);return null;}5. 关于树化(转成红黑树)//如果 table 为 null ,或者大小还没有到 64,暂时不树化,而是进行扩容. //否则才会真正的树化 -> 剪枝final void treeifyBin (Node < K, V >[]tab,int hash){int n, index;Node<K, V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize();}*/

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

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

相关文章

[Linux]命令行参数和进程优先级

[Linux]命令行参数和进程优先级 文章目录 [Linux]命令行参数和进程优先级命令行参数命令行参数的概念命令函参数的接收编写代码验证 进程优先级进程优先级的概念PRI and NI使用top指令修改nice值 命令行参数 命令行参数的概念 命令行参数是指用于运行程序时在命令行输入的参数…

Qt6和Rust结合构建桌面应用

桌面应用程序是原生的、快速的、安全的&#xff0c;并提供Web应用程序无法比拟的体验。 Rust 是一种低级静态类型多范式编程语言&#xff0c;专注于安全性和性能&#xff0c;解决了 C/C 长期以来一直在努力解决的问题&#xff0c;例如内存错误和构建并发程序。 在桌面应用程序开…

ToolAI–全球最完整最全面的AI人工智能工具集合

ToolAI是一个全球最完整最全面的AI人工智能工具集合网站&#xff0c;收集了全球最完整的数千个AI网站、工具、app&#xff0c;包含文案写作、邮件助手、聊天机器人、社交媒体等等各种行业类型的AI工具&#xff0c;可以按照地区或者分类进行查找浏览&#xff0c;目前收集6800 人…

垃圾回收器

垃圾回收器就是垃圾回收的实践者&#xff0c;随着JDK的发展&#xff0c;垃圾回收器也在不断的更迭&#xff0c;在不同的场合下使用不同的垃圾回收器&#xff0c;这也是JVM调优的一部分。 1.垃圾回收器的分类 按线程可分为单线程(串行)垃圾回收器和多线程(并行)垃圾回收器。 按…

Java之ApI之Math类详解

1 Math类 1.1 概述 tips&#xff1a;了解内容 查看API文档&#xff0c;我们可以看到API文档中关于Math类的定义如下&#xff1a; Math类所在包为java.lang包&#xff0c;因此在使用的时候不需要进行导包。并且Math类被final修饰了&#xff0c;因此该类是不能被继承的。 Math类…

Unity 之 GameObject.Find()在场景中查找指定名称的游戏对象

文章目录 GameObject.Find 是 Unity 中的一个函数&#xff0c;用于在场景中查找指定名称的游戏对象。这个函数的主要作用是根据游戏对象的名称来查找并返回一个引用&#xff0c;使您能够在代码中操作该对象。以下是有关 GameObject.Find 的详细介绍&#xff1a; 函数签名&…

某网站DES加密逆向分析实战

文章目录 一、抓包分析二、加密分析一、重写加密 一、抓包分析 分析站点&#xff1a; aHR0cDovL2VpcC5jaGFuZmluZS5jb20v 首先我们提交一下登陆信息&#xff1a; 搜索j_password查看加密函数: 把上图搜索到的encryptPassword函数拿出来分析一下&#xff1a; function encryptP…

智慧能源管理系统助力某制造企业提高能源利用效率

随着全球能源需求不断增加和能源价格的上涨&#xff0c;企业和机构日益意识到能源管理的重要性。传统的能源管理方式不仅效率低下&#xff0c;还容易造成资源浪费和环境污染。因此&#xff0c;许多企业开始探索采用智慧能源管理系统来提高能源利用效率&#xff0c;降低能源成本…

【面向大一新生IT技术社群招新啦,不来瞅瞅?】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生 &#x1f43b;‍❄️个人主页&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;落798. &#x1f54a;️系列专栏&#xff1a;【零基础学java】 ----- 【重识c语言】 ---- 【计算机网络】—【Spri…

python爬虫-网页数据提取

import requests #headers 网页右键->Network->最下面的User-Agent复制。 headers {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"} #你想要的网址 url &q…

Java设计模式-职责链模式

1 概述 在现实生活中&#xff0c;常常会出现这样的事例&#xff1a;一个请求有多个对象可以处理&#xff0c;但每个对象的处理条件或权限不同。例如&#xff0c;公司员工请假&#xff0c;可批假的领导有部门负责人、副总经理、总经理等&#xff0c;但每个领导能批准的天数不同…

【ArcGIS微课1000例】0073:ArcGIS探索性回归分析案例

一、探索性回归工具简介 “探索性回归”工具会对输入的候选解释变量的所有可能组合进行评估,以便根据用户所指定的指标来查找能够最好地对因变量做出解释的 OLS 模型。 给定一组候选解释变量,找出正确指定的 OLS 模型: 用法: 工具还会生成一个可选表,该表包括所有满足…

06-Numpy基础-线性代数

线性代数&#xff08;如矩阵乘法、矩阵分解、行列式以及其他方阵数学等&#xff09;是任何数组库的重要组成部分。 NumPy提供了一个用于矩阵乘法的dot函数&#xff08;既是一个数组方法也是numpy命名空间中的一个函数&#xff09; x.dot(y)等价于np.dot(x, y) 符&#xff08;…

2023年高教社杯 国赛数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

MongoDB Long 类型 shell 查询

场景 1、某数据ID为Long类型&#xff0c;JAVA 定义实体类 Id Long id 2、查询数据库&#xff0c;此数据存在 3、使用 shell 查询&#xff0c;查不到数据 4、JAVA代码查询Query.query 不受任何影响 分析 尝试解决&#xff08;一&#xff09; long 在 mongo中为 int64 类型…

【android12-linux-5.1】【ST芯片】HAL移植后没调起来

ST传感器芯片HAL按官方文档移植后&#xff0c;测试一直掉不起来&#xff0c;加的日志没出来。经过分析&#xff0c;是系统自带了一个HAL&#xff0c;影响的。 按照官方文档&#xff0c;移植HAL后&#xff0c;在/device/<vendor\>/<board\>/device.mk*路径增加PROD…

运维高级学习--Kubernetes(K8s 1.28.x)部署

一、基础环境配置&#xff08;所有主机操作&#xff09; 主机名规划 序号 主机ip 主机名规划1 192.168.1.30 kubernetes-master.openlab.cn kubernetes-master2 192.168.1.31 kubernetes-node1.openlab.cn kubernetes-node13 192.168.1.32 kubernetes-node2…

从零开始的Hadoop学习(二)| Hadoop介绍、优势、组成、HDFS架构

1. Hadoop 是什么 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。广义上来说&#xff0c;Hadoop通常是指一个更广泛的概念—Hadoop生态圈。 2. Hadoop 的优势 高可靠性&#xff1a;Hadoop底层维护多…

动态表情包怎么制作?分享一个一键生成gif动图的方法

跟朋友聊天时&#xff0c;经常会用很多有趣的表情包给朋友回复&#xff0c;那么除了利用系统提供的gif动画包&#xff0c;怎么才能完成gif图片制作&#xff08;https://www.gif.cn&#xff09;呢&#xff1f;下面就为大家分享一个一键生成gif动图的方法&#xff0c;通过简单的操…

React 18 用 State 响应输入

参考文章 用 State 响应输入 React 控制 UI 的方式是声明式的。不必直接控制 UI 的各个部分&#xff0c;只需要声明组件可以处于的不同状态&#xff0c;并根据用户的输入在它们之间切换。这与设计师对 UI 的思考方式很相似。 声明式 UI 与命令式 UI 的比较 当设计 UI 交互时…