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

news2024/12/23 13:19:50

文章目录

  • 前言
  • 一、概述
    • 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

总结

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

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

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

相关文章

3DS Max中绘制圆锥箭头

3DS Max中绘制圆锥箭头 绘制结果绘制过程步骤一&#xff1a;绘制立体圆锥方法1方法2 步骤二&#xff1a;圆锥体调参&#xff08;模型尺寸设置&#xff09;1圆锥体参数说明2圆锥体参数调整 步骤三&#xff1a;绘制圆柱体步骤四&#xff1a;圆柱体调参步骤五&#xff1a;圆锥与圆…

安达发|富士康科技集团利用自动排程APS软件打造智慧工厂

富士康科技集团作为全球领先的3C产品研发制造企业&#xff0c;近年来积极布局智能制造领域&#xff0c;通过引入先进的自动化排程系统(APS),成功打造了智慧工厂&#xff0c;提高了生产质量与效率&#xff0c;降低了生产成本。 富士康集团自2019年下半年提出在观澜厂区建立数字可…

dji所有机型,价格,发布日期,最大飞行时间

机型价格发布日期最大飞行时间DJI Mini 3 Pro9999 元2023 年 1 月 20 日30 分钟DJI Air 36988 元2022 年 6 月 29 日46 分钟DJI Air 2S9988 元2021 年 7 月 25 日31 分钟DJI Mavic 313999 元2021 年 11 月 5 日46 分钟DJI Mavic 3 Cine16999 元2021 年 11 月 5 日46 分钟DJI Ma…

【算法与数据结构】513、LeetCode找树左下角的值

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题用层序遍历来做比较简单&#xff0c;最底层最左边节点就是层序遍历当中最底层元素容器的第一个值…

【网络安全带你练爬虫-100练】第17练:分割字符串

目录 一、目标1&#xff1a;使用函数分割 二、目标2&#xff1a;使用函数模块 三、目标3&#xff1a;使用正则匹配 一、目标1&#xff1a;使用函数分割 目标&#xff1a;x.x.x.x[中国北京 xx云] 方法&#xff1a;split函数replace函数 1、分割&#xff1a;使用split()方法将…

LAMP 配置与应用

LAMP 架构的组成 LAM(M)P&#xff1a; L&#xff1a;linux A&#xff1a;apache (httpd) M&#xff1a;mysql, mariadb P&#xff1a;php, perl, python apache的功能&#xff1a; 第一&#xff1a;处理http的请求、构建响应报文等自身服务&#xff1b; 第二&#xff1a…

android手机销售app(IDEA,SpringBoot,SSM,MySQL)+支付宝支付+全套视频教程

本项目亮点: 支付宝支付 eCharts柱状图图表数据统计 【项目功能介绍】 本系统包含后台管理和前端app双端系统&#xff0c;后台管理的功能包含: 登录, 退出, 修改管理员信息(基本信息与头像),资源管理,角色管理,资源权限分配,字典管理,用户管理,图书管理,订单管理,订单统计; a…

Java BigDecimal详解

目录 一、前言 二、BigDecimal 2.1、常用构造方法 2.2、常用方法 2.3、示例代码 add(BigDecimal)方法 subtract(BigDecimal)方法 multiply(BigDecimal)方法 divide(BigDecimal)方法 max(BigDecimal val)方法 2.4、BigDecimal的八种舍入模式 setScale(1) setScale(…

CAN接口:Ubuntu系统下CAN接口使用python调用过程

CAN接口&#xff1a;Ubuntu系统下CAN接口使用python调用过程 介绍在Ubuntu系统中通过python程序使用CAN接口。 1. 使用平台 NVIDIA小型边缘设备NX&#xff0c;&#xff08;Orin NX和Xavier NX都可以&#xff09;&#xff0c;系统采用Ubuntu&#xff0c;&#xff08;18.04版本…

ASSY 11994R13PLC模块

可编程性&#xff1a; PLC模块可以通过编程进行定制&#xff0c;以执行特定的控制逻辑和功能。这种可编程性使其非常灵活&#xff0c;可以适应各种应用。 输入/输出&#xff08;I/O&#xff09;&#xff1a; PLC模块通常具有数字输入和输出&#xff0c;以接收和发送信号。某些…

喜报|星瑞格荣获“2022-2023年度国产数据库应用优秀解决方案”奖项

近日&#xff0c;赛迪网为表彰数字赛道上的先行者&#xff0c;联合《数字经济》杂志社和北京科创互联&#xff0c;共同组织以“树立行业标杆&#xff0c;引领服务创新”为中心的“2022-2023年度产业数字服务案例及创新成果征集活动”。该活动旨在鼓励各行业数字化应用技术创新树…

【ag-grid-vue】列定义(Updating Column Definitions)

列定义一节解释了如何配置列。可以在初始设置列之后更改列的配置。本节介绍如何更新列定义。 添加和删除列 可以通过更新提供给网格的列定义列表来添加和删除列。当设置新列时&#xff0c;网格将与当前列进行比较&#xff0c;并计算出哪些列是旧的(要删除)、哪些列是新的(创建…

增加samba用户提示Failed to add entry for user

这个问题我在CSDN上搜到了很多文章&#xff0c;而且都差不多&#xff0c;一开始并没有解决我的问题&#xff0c;不太理解怎么做&#xff0c;经过多次尝试&#xff0c;最后解决了。记录一下具体操作步骤。 第一个是要配置/etc/samba/smb.conf 文件&#xff0c;在文件最后&#x…

技术漫谈第10期 | “百模大战”:向着行业更深处

自21世纪初以来&#xff0c;人工智能&#xff08;AI&#xff09;已经从科幻小说中的概念成长为现实生活中的重要工具。从符号推理到弱人工智能再到大规模深度学习模型&#xff0c;人工智能已经进入大模型时代的新阶段&#xff0c;是科技竞争的制高点&#xff0c;即将改变千行百…

手把手教你安装Git,萌新迈向专业的必备一步

手把手教你安装Git&#xff0c;萌新迈向专业的必备一步 一、版本控制系统是什么&#xff1f;1. 倒霉的小明2. 版本控制系统3. 常见的版本控制系统 二、GitLab 与 GitHub1. GitLab2. GitHub 三、Git安装1. 下载2. 安装3. 验证 四、初学使用1. 本地仓库2. 远程仓库-Github3. 远程…

关于安防视频汇聚平台EasyCVR视频平台的分析以及应用用途

为了保证对园区环境风险进行有效识别&#xff0c;传统视频监控存在视频结构化利用率低的问题&#xff0c;在实际使用过程中&#xff0c;安全管理人员工作效率低下&#xff0c;依靠人工肉眼查看灵活度低&#xff0c;风险漏报概率高&#xff0c;出现异常情况跟踪不及时&#xff0…

post为什么会发送两次请求

今天看掘金的文章&#xff0c;京东面试问了这个问题&#xff0c;我也处于好奇&#xff0c;想了解这块的内容所以做了以下的来了解&#xff1a; 请求是一对请求&#xff0c;有一次请求是预请求&#xff08;预检请求&#xff09;&#xff0c;它的请求方式是options 火狐浏览器可…

long型的时间戳自动转化为字符串

1、自定义序列化类 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase;JacksonStdImpl public class ToDateStringSerializer extends ToStringSerializerBase {public ToDateStringS…

AP9234 9W升压恒流型 DCDC多串LED恒流驱动 2串3串 LED灯串

描述 AP9234是一款由基准电压源、振荡电路、误差放大电路、相位补偿电路、电流限制电路等构成的CMOS升压型DC/DC LED驱动。由于内置了低导通电阻的增强型N沟道功率MOSFET&#xff0c;因此适用于需要高效率、高输出电流的应用电路。另外&#xff0c;可通过在VSENSE端子连接电流…

SpringBoot扩展接口总结

SpringBoot 扩展接口 1、可扩展接口启动调用概述2、可扩展的点逐个说明2.1、ApplicationContextInitializer2.2、BeanDefinitionRegistryPostProcessor2.3、BeanFactoryPostProcessor2.4、InstantiationAwareBeanPostProcessor2.5、SmartInstantiationAwareBeanPostProcessor2.…