提升Java开发效率:掌握HashMap的常见方法与基本原理

文章目录

  • 前言
  • 一、概述
    • 1. 认识HashMap
    • 2. HashMap 的作用和重要性
    • 3. 简要讲解 HashMap 的基本原理和实现方式
  • 二、了解 HashMap 创建及其的常见操作方法
    • 1. HashMap的创建
    • 2. 添加元素 put()
    • 3. 访问元素 get()
    • 4. 删除元素 remove()
    • 5. 计算大小 size()
    • 6. 迭代 HashMap for-each
    • 7.判断是否为空 isEmpty()
    • 8. 判断 HashMap 中是否存在指定 key containsKey()
    • 9. 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 getOrDefault()
  • 总结


前言

为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)

一、概述

1. 认识HashMap

  • HashMap 是一个散列表,它存储的内容是键值对(key-value)映射

  • HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步

  • HashMap 是无序的,即不会记录插入的顺序

  • HashMap 继承于AbstractMap,实现了 MapCloneablejava.io.Serializable 接口

在这里插入图片描述

  • HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value

2. HashMap 的作用和重要性

HashMap是Java中最常用的数据结构之一,它实现了 Map 接口,提供了键值对存储和检索的功能。HashMap 的作用和重要性体现在以下几个方面:

  • 存储和检索:HashMap 可以存储大量的键值对数据,并通过键快速检索对应的值。它使用哈希算法将键映射到数组的位置,从而实现高效的查找操作。这使得HashMap在处理大量数据时,可以快速地插入、获取和删除元素。
  • 高效性能:由于 HashMap 的内部实现利用了哈希算法,它的查找操作的平均时间复杂度为O(1)(常数时间)。这意味着HashMap 在大多数情况下能够以非常高效的方式执行插入和查找操作,使得它成为处理大规模数据的理想选择。
  • 灵活性:HashMap 中的键和值可以是任意类型的对象。这使得我们可以根据具体需求将不同类型的数据存储在 HashMap 中,而不受限于特定的数据类型
  • 唯一键:HashMap 要求键的唯一性,这意味着每个键只能在 HashMap 中出现一次。这对于通过键来查找值的场景非常有用,例如存储用户信息时,可以将用户ID作为键,以便快速地检索该用户的信息。
  • 扩展性:HashMap 可以动态地扩展,根据存储数据的增长自动调整容量,从而避免了手动进行容量管理的繁琐操作。

3. 简要讲解 HashMap 的基本原理和实现方式

当使用 HashMap 存储数据时,它会根据键的哈希值将键值对映射到内部的数组中。基本原理可以概括为以下几步:

1. HashMap函数

  • 哈希函数:哈希表中元素是由哈希函数确定的,将数据元素的关键字 Key 作为自变量,通过一定的函数关系(称为哈希函数),计算出的值,即为该元素的存储地址。哈希表中哈希函数的设计是相当重要的,这也是建哈希表过程中的关键问题之一

  • 哈希函数计算:当我们向HashMap中插入一个键值对时,HashMap会调用键的hashCode()方法来计算其哈希值。哈希值是一个整数,用于将键映射到数组的索引位置

  • 哈希值转换:为了确保哈希值适合作为数组的索引,HashMap会对计算得到的哈希值进行一些转换操作。常用的转换方法是使用哈希值与数组长度进行取模运算,得到一个在数组范围内的索引值

在这里插入图片描述

2. HashMap存储

  • 数组存储:HashMap内部维护了一个数组每个数组元素对应一个桶(bucket)。每个桶可以存储一个或多个键值对。当插入或查找元素时,HashMap根据计算得到的索引值找到对应的桶,然后在桶中进行相应的操作

  • 动态扩容:为了提高HashMap的性能,在存储的键值对数量达到一定阈值后,HashMap会自动进行扩容操作。扩容过程涉及重新计算键的哈希值,并重新分配键值对到更大的数组中。这样可以减少哈希冲突,提高操作效率

在这里插入图片描述

3. HashMap冲突处理

  • 冲突处理:由于不同的键可能具有相同的哈希值,这就会导致冲突。当发生冲突时,HashMap使用链表或红黑树等数据结构来存储具有相同哈希值的键值对。这些数据结构允许在冲突的位置上存储多个键值对,并通过比较键的equals()方法来区分它们

  • 链表:在JDK 8之前,HashMap使用链表来解决冲突。当多个键值对被映射到同一个桶时,它们会形成一个链表。通过遍历链表来查找、插入或删除键值对。但是,当链表长度过长时,会影响HashMap的性能

  • 红黑树:从JDK 8开始,当链表长度超过一个阈值(默认为8)时,链表会被自动转换为红黑树,以提高操作效率。红黑树的查找、插入和删除操作具有较低的时间复杂度,可以在平均情况下保持对数时间复杂度

在这里插入图片描述

  • Entry对象:HashMap使用Entry对象来表示键值对。每个Entry对象包含了键、值以及指向下一个Entry的引用(形成链表或红黑树结构)。在JDK 8之前,每个Entry对象还包含了指向前一个Entry的引用,以支持快速删除操作

总的来说,HashMap 通过哈希函数计算键的哈希值,并将键值对映射到内部数组中的桶中。采用链表或红黑树等数据结构解决哈希冲突,并通过动态扩容来提高性能。这种实现方式使得 HashMap 能够在常数时间复杂度内执行插入、查找和删除操作。

二、了解 HashMap 创建及其的常见操作方法

1. HashMap的创建

1. 关于包装类
HashMap 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类,基本类型对应的包装类表如下:

基本类型引用类型
booleanBoolean
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter

2. HashMap要使用包装类型而不是基本类型

  • 泛型限制HashMap 是一个泛型类,它可以存储任意类型的键和值。然而,泛型类型参数只能是类而不能是基本类型。因此,如果要将基本类型作为键或值存储在 HashMap 中,就需要将其包装为相应的包装类型,例如 Integer、Double、Boolean 等。

  • 空值处理基本类型是不允许为 null 的,而包装类型可以为 null。在 HashMap 中,键和值都可以为 null。对于基本类型,当我们需要在 HashMap 中存储一个空值时,必须使用对应的包装类型。

3. 创建HashMap的示例

  • HashMap 类位于 java.util 包中,使用前需要引入它,语法格式如下:
import java.util.HashMap; // 引入 HashMap 类
  • 以下实例我们创建一个 HashMap 对象 Sites, 整型(Integer)的 key 和字符串(String)类型的 value:
HashMap<Integer, String> Sites = new HashMap<Integer, String>();

2. 添加元素 put()

  • 要向HashMap添加元素,你可以使用 put() 方法。put() 方法接受两个参数,第一个参数是键(Key)第二个参数是值(Value)。以下是一个添加元素到 HashMap 的示例:
  map.put("A", 1);map.put("B", 2);map.put("C", 3);
  • 需要注意的是,HashMap 允许将null作为键和值。如果你尝试将null作为键添加到 HashMap 中,它将只有一个键为 null 的键值对。另外,由于 HashMap 不是线程安全的,如果在多线程环境下使用 HashMap,请考虑使用线程安全的 ConcurrentHashMap

3. 访问元素 get()

  • 要访问HashMap中的元素,你可以使用 get() 方法。get() 方法接受一个参数,即要获取的键(Key),并返回该键关联的值(Value)
  int value1 = map.get("A"); // 访问键为"A"的值int value2 = map.get("B"); // 访问键为"B"的值
  • 需要注意的是,如果指定的键不存在于 HashMap 中,get() 方法将返回 null。因此,在使用 get() 方法获取值之前,最好先使用containsKey() 方法 检查 HashMap 中是否存在指定的键

  • 另外,HashMap还提供了其他方法来访问元素,如keySet()方法可返回所有键的集合values()方法可返回所有值的集合entrySet()方法可返回包含键值对的集合。通过使用这些方法,你可以遍历HashMap中的所有键值对并执行相应的操作

4. 删除元素 remove()

  • 使用 remove(Object key) 方法:这个方法接受一个键作为参数,并从 HashMap 中删除对应的键值对。例如,如果你要删除键为 “key1” 的元素,可以使用以下代码:
  HashMap<String, String> hashMap = new HashMap<>();hashMap.remove("key1");
  • 使用迭代器遍历并删除元素:你可以使用 Iterator 来遍历 HashMap 的键值对,并使用 remove() 方法删除元素。这种方法适用于需要按条件删除元素的情况。例如,如果你要删除所有值为"value1"的键值对,可以使用以下代码:
HashMap<String, String> hashMap = new HashMap<>();
Iterator<Map.Entry<String, String>> iterator = hashMap.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, String> entry = iterator.next();if (entry.getValue().equals("value1")) {iterator.remove();}
}
  • 删除所有键值对 (key-value) 可以使用 clear 方法:
 hashMap.clear();

5. 计算大小 size()

  • 要计算HashMap的大小(即键值对的数量),你可以使用size()方法。该方法返回HashMap中键值对的数量。
  • 以下是使用size()方法计算HashMap大小的示例代码:
  int size = hashMap.size();

6. 迭代 HashMap for-each

  • 可以使用 for-each 来迭代 HashMap 中的元素

  • 如果你只想获取 key,可以使用 keySet() 方法,然后可以通过 get(key) 获取对应的 value,如果你只想获取 value,可以使用 values() 方法

// 引入 HashMap 类      
import java.util.HashMap;public class RunoobTest {public static void main(String[] args) {// 创建 HashMap 对象 SitesHashMap<Integer, String> Sites = new HashMap<Integer, String>();// 添加键值对Sites.put(1, "Google");Sites.put(2, "Runoob");Sites.put(3, "Taobao");Sites.put(4, "Zhihu");// 输出 key 和 valuefor (Integer i : Sites.keySet()) {System.out.println("key: " + i + " value: " + Sites.get(i));}// 返回所有 value 值for(String value: Sites.values()) {// 输出每一个valueSystem.out.print(value + ", ");}}
}
  • 执行以上代码,输出结果如下:

key: 1 value: Google
key: 2 value: Runoob
key: 3 value: Taobao
key: 4 value: Zhihu
Google, Runoob, Taobao, Zhihu,

7.判断是否为空 isEmpty()

  • 要判断HashMap是否为空,你可以使用isEmpty()方法。该方法会返回一个布尔值,表示HashMap是否为空

  • 以下是使用isEmpty()方法判断HashMap是否为空的示例代码:

 System.out.println("Is HashMap empty? " + hashMap.isEmpty()

8. 判断 HashMap 中是否存在指定 key containsKey()

  • 要判断 HashMap 是否包含某个特定的键(key),你可以使用 containsKey(Object key) 方法。该方法接受一个键作为参数,并返回一个布尔值,表示 HashMap 是否包含该键

  • 以下是使用 containsKey(Object key) 方法判断 HashMap 是否包含某个键的示例代码:

System.out.println("Does HashMap contain key 'key2'? " + hashMap.containsKey("key1"));

9. 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 getOrDefault()

  • getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值

  • getOrDefault() 方法的语法为:

hashmap.getOrDefault(Object key, V defaultValue)

  • 参数说明:

1. key - 键
2. defaultValue - 当指定的key并不存在映射关系中,则返回的该默认值

  • 返回值:返回 key 相映射的的 value,如果给定的 key 在映射关系中找不到,则返回指定的默认值
import java.util.HashMap;class Main {public static void main(String[] args) {// 创建一个 HashMapHashMap<Integer, String> sites = new HashMap<>();// 往 HashMap 添加一些元素sites.put(1, "Google");sites.put(2, "Runoob");sites.put(3, "Taobao");System.out.println("sites HashMap: " + sites);// key 的映射存在于 HashMap 中// Not Found - 如果 HashMap 中没有该 key,则返回默认值String value1 = sites.getOrDefault(1, "Not Found");System.out.println("Value for key 1:  " + value1);// key 的映射不存在于 HashMap 中// Not Found - 如果 HashMap 中没有该 key,则返回默认值String value2 = sites.getOrDefault(4, "Not Found");System.out.println("Value for key 4: " + value2);}
}
  • 执行以上程序输出结果为:

Value for key 1: Google
Value for key 4: Not Found

总结

欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)

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

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

相关文章

【C++】C++ 引用详解 ⑨ ( 常量引用初始化 | C / C++ 常量分配内存的四种情况 )

文章目录 一、常量引用初始化1、使用 " 普通变量 " 初始化 " 常量引用 "2、使用 " 常量 / 字面量 " 初始化 " 常量引用 "3、C / C 常量分配内存的四种情况4、代码示例 - 常量引用初始化 一、常量引用初始化 1、使用 " 普通变量 &…

消息中间件 介绍

MQ简介 MQ,Message queue,消息队列&#xff0c;就是指保存消息的一个容器。具体的定义这里就不类似于数据库、缓存等&#xff0c;用来保存数据的。当然&#xff0c;与数据库、缓存等产品比较&#xff0c;也有自己一些特点&#xff0c;具体的特点后文会做详细的介绍。 现在常用…

使用 ChatGPT 创建 PowerPoint 演示文稿

让 ChatGPT 成为您的助手来帮助您编写电子邮件很简单,因为众所周知,它非常能够生成文本。很明显,ChatGPT 无法帮助您做饭。但您可能想知道它是否可以生成文本以外的其他内容。在上一篇文章中,您了解到 ChatGPT 只能通过中间语言为您生成图形。在这篇文章中,您将了解使用中…

研磨设计模式day12迭代器模式

目录 场景 解决方案 解决思路 代码示例 代码改造 Java实现迭代器 迭代器模式的优点 思考 何时选用 场景 大公司收购了一个小公司&#xff0c;大公司的工资系统采用List来记录工资列表&#xff0c;而小公司是采用数组&#xff0c;老板希望通过决策辅助系统来统一查看…

VUE笔记(一)初识vue

一、vue的简介 1、什么是vue 官网地址:Vue.js Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。 构建用户界面&#xff1a;之前在学习vue之前通过原生js对DOM操作进行构建用户界面的 使用原生js构建用户界面的不足 - 没有规范&#xff0c…

IDEA的maven想显示层级关系,而非平级

新版和旧版的IDEA的位置不一样&#xff0c;2023.2.1的版本在右上角的“” 这个位置 如图所示&#xff1a; 然后点击按模块分组&#xff1a;

【PostGreSQL】PostGreSQL到Oracle的数据迁移

项目需要&#xff0c;有个数据需要导入&#xff0c;拿到手一开始以为是mysql&#xff0c;结果是个PostGreSQL的数据&#xff0c;于是装数据库&#xff0c;但这个也不懂呀&#xff0c;而且本系统用的Oracle&#xff0c;于是得解决迁移转换的问题。 总结下来两个思路。 1、Postg…

芯片 半导体 晶圆

芯片&#xff08;chip&#xff09;就是半导体元件产品的统称&#xff0c;是 集成电路&#xff08;IC&#xff0c; integrated circuit&#xff09;的载体&#xff0c;由晶圆分割而成。 半导体集成电路是将很多元件集成到一个芯片内, 以处理和储存各种功能的电子部件。由于半导…

error: can‘t find Rust compiler

操作系统 win11 pip install -r requirements.txt 报错如下 Using cached https://pypi.tuna.tsinghua.edu.cn/packages/56/fc/a3c13ded7b3057680c8ae95a9b6cc83e63657c38e0005c400a5d018a33a7/pyreadline3-3.4.1-py3-none-any.whl (95 kB) Building wheels for collected p…

2023河南萌新联赛第(六)场:河南理工大学 C - 旅游

2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学 C - 旅游 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K Special Judge, 64bit IO Format: %lld 题目描述 小C喜欢旅游&#xf…

科大讯飞永久免费GPT入口来了!!!

讯飞GPT永久免费使用入口注册链接&#xff1a;讯飞星火认知大模型-AI大语言模型-星火大模型-科大讯飞。 登录讯飞账号后&#xff0c;点击进入体验。 进入体验页面后&#xff0c;选择景点推荐。 笔者让其写一篇关于讯飞GPT介绍的文案。 讯飞GPT是一款由讯飞公司推出的人工智能语…

Linux环境下SVN服务器的搭建与公网访问:使用cpolar端口映射的实现方法

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…