提升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 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        // 输出 key 和 value
        for (Integer i : Sites.keySet()) {
            System.out.println("key: " + i + " value: " + Sites.get(i));
        }
        // 返回所有 value 值
        for(String value: Sites.values()) {
          // 输出每一个value
          System.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) {
        // 创建一个 HashMap
        HashMap<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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浏览器输入一个URL之后发生了什么?

URL解析DNS解析TCP连接TSL连接HTTP请求TCP挥手接收并解析响应 URL 解析 主要分为&#xff1a; 协议&#xff0c;eg http,https域名或者ip地址&#xff0c;eg www.baidu.com 域名相对于ip地址来说&#xff0c;更方便人们记忆&#xff0c;但是实际的网络传输中使用的是ip地址 端…

Redis 7 教程 数据持久化

总体 RDB 介绍 RDB 持久化以指定的时间间隔执行数据集的时间点快照 。 把某一时刻的数据和状态以文件的形式写到磁盘上,即使出现故障宕机,快照文件也不会丢失,数据的可靠性得到保证。快照文件就是RDB(Redis DataBase)文件(dump.rdb) 作用 在指定的时间间隔内将内存中的数…

leetcode304. 二维区域和检索 - 矩阵不可变(java)

前缀和数组 二维区域和检索 - 矩阵不可变题目描述前缀和代码演示 一维数组前缀和 二维区域和检索 - 矩阵不可变 难度 - 中等 原题链接 - 二维区域和检索 - 矩阵不可变 题目描述 给定一个二维矩阵 matrix&#xff0c;以下类型的多个请求&#xff1a; 计算其子矩形范围内元素的总…

FreeSWITCH 1.10.10 简单图形化界面3 - 阿里云NAT设置

FreeSWITCH 1.10.10 简单图形化界面3 - 阿里云NAT设置 0、 界面预览1、 查看IP地址2、 修改协议配置3、 开放阿里云安全组4、 设置ACL5、 设置协议中ACL&#xff0c;让PBX匹配内外网6、 重新加载SIP模块7、 查看状态8、 测试一下 0、 界面预览 http://myfs.f3322.net:8020/ 用…

面试之快速学习STL-常用算法

1. 排序算法 sort() 函数是基于快速排序实现的&#xff0c;故不保证相对位置&#xff0c;但是stable_sort (first, last)保证&#xff0c;它基于归并排序。sort()只适用于支持随机迭代器的容器&#xff08;array, vector, deque&#xff09;&#xff0c;好理解&#xff0c;毕竟…

3d素材库素材资源平台大大节省老师备课时间

教育元宇宙相信大家有所耳闻&#xff0c;3D素材云库通过数字三维建模技术将现实中的物体、天气、灯光等1&#xff1a;1模拟还原到虚拟场景中&#xff0c;让人们在教育元宇宙平台中可视、可见、可感。 在元宇宙爆发的大背景下&#xff0c;3D互联网传播内容也将迎来一次全面升级&…

java八股文面试[java基础]——如何实现不可变的类

知识来源&#xff1a; 【23版面试突击】如何实现不可变的类&#xff1f;_哔哩哔哩_bilibili 【2023年面试】怎样声明一个类不会被继承&#xff0c;什么场景下会用_哔哩哔哩_bilibili

leetcode 567. 字符串的排列(滑动窗口-java)

滑动窗口 字符串的排列滑动窗口代码演示进阶优化版 上期经典 字符串的排列 难度 -中等 leetcode567. 字符串的排列 给你两个字符串 s1 和 s2 &#xff0c;写一个函数来判断 s2 是否包含 s1 的排列。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 换句…

Focal Loss-解决样本标签分布不平衡问题

文章目录 背景交叉熵损失函数平衡交叉熵函数 Focal Loss损失函数Focal Loss vs Balanced Cross EntropyWhy does Focal Loss work? 针对VidHOI数据集Reference 背景 Focal Loss由何凯明提出&#xff0c;最初用于图像领域解决数据不平衡造成的模型性能问题。 交叉熵损失函数 …

用AI重构的钉钉,“钱”路在何方?

点击关注 文&#xff5c;郝 鑫&#xff0c;编&#xff5c;刘雨琦 钉钉2023年生态大会&#xff0c;离开了两年的无招&#xff0c;遇到了单飞9天的钉钉。 “做小钉钉、做好钉钉、做酷钉钉”&#xff0c;无招重申了钉钉的方向。 无招提到的三点&#xff0c;再加上“高质量增长”…

Doris异常处理

1、decimal 字段异常 修改为 2、连接超时 Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure The last packet successfully received from the server was 1,068 milliseconds ago. The last packet sent successfully to the ser…

Redis限流实践:实现用户消息推送每天最多通知2次的功能

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

Docker数据管理(数据卷与数据卷容器)

目录 一、数据卷&#xff08;Data Volumes&#xff09; 1、概述 2、原理 3、作用 4、示例&#xff1a;宿主机目录 /var/test 挂载同步到容器中的 /data1 二、数据卷容器&#xff08;DataVolumes Containers&#xff09; 1、概述 2、作用 3、示例&#xff1a;创建并使用…

AIGC ChatGPT 实现动态多维度分析雷达图制作

雷达图在多维度分析中是一种非常实用的可视化工具,主要有以下优势: 易于理解:雷达图使用多边形或者圆形的形式展示多维度的数据,直观易于理解。多维度对比:雷达图可以在同一张图上比较多个项目或者实体在多个维度上的表现。数据关系明显:通过雷达图,可以直观的看出各个数…

C++贪吃蛇(控制台版)

C自学精简实践教程 目录(必读) 目录 主要考察 需求 输入文件 运行效果 实现思路 枚举类型 enum class 启动代码 输入文件data.txt 的内容 参考答案 学生实现的效果 主要考察 模块划分 文本文件读取 UI与业务分离 控制台交互 数据抽象 需求 用户输入字母表示方…

朋友圈也可以定时定量发送?

场景1&#xff1a;明天要搞活动&#xff0c;早中晚都得发朋友圈&#xff0c;一天要发3次朋友圈&#xff0c;要在手机上定好3个闹钟&#xff0c;这是一件非常麻烦的事。 场景2&#xff1a;有朋友是房产信息的&#xff0c;每天要发布很多二手房源&#xff0c;手动发圈太耗时间&a…

记录:yolov8训练自己的数据集

一、LabelImg标注自己的原图数据集 .xml标注格式 二、带标签的数据增强 先将原始数据&#xff08;图片&#xff0c;标注&#xff09;转移到项目根目录&#xff0c;然后再数据增强&#xff0c;避免标注内容路径错误。 亮度变换加旋转 # 一、亮度 img_dir multi/images # 原始…

CSS基础选择器及常见属性

文章目录 一、CSS1、CSS简介2、CSS语法规范 二、CSS基础选择器1、选择器的作用2、选择器分类3、基础选择器标签选择器类选择器id选择器通配符选择器 三、CSS常见属性1、字体属性字体系列字体大小字体粗细文字样式 2、文本属性文本颜色对齐文本装饰文本文本缩进行间距 四、CSS引…

python编写四画面同时播放swap视频

当代技术让我们能够创建各种有趣和实用的应用程序。在本篇博客中&#xff0c;我们将探索一个基于wxPython和OpenCV的四路视频播放器应用程序。这个应用程序可以同时播放四个视频文件&#xff0c;并将它们显示在一个GUI界面中。 C:\pythoncode\new\smetimeplaymp4.py 准备工作…

2023最新任务悬赏平台源码uniapp+Thinkphp新款悬赏任务地推拉新充场游戏试玩源码众人帮威客兼职任务帮任务发布分销机

新款悬赏任务地推拉新充场游戏试玩源码众人帮威客兼职任务帮任务发布分销机制 后端是&#xff1a;thinkphpFastAdmin 前端是&#xff1a;uniapp 1.优化首页推荐店铺模块如有则会显示此模块没有则隐藏。 2修复首页公告&#xff0c;更改首页公告逻辑。&#xff08;后台添加有公…