【Java】HashMap的简单教程

HashMap 是 Java 中最常用的数据结构之一,属于 java.util 包,主要用于以键值对(key-value)形式存储数据。

基本用法

1.创建

HashMap 使用泛型,存储键值对。

import java.util.HashMap;

HashMap<KeyType, ValueType> map = new HashMap<>();
  • 默认构造方法
HashMap<String, Integer> map = new HashMap<>();
  • 指定初始容量

指定初始容量可以避免频繁扩容。

HashMap<String, Integer> map = new HashMap<>(32);
  • 指定初始容量和负载因子

加载因子默认是0.75,当元素个数达到 容量 * 负载因子 时,HashMap 会触发扩容

意思是:默认数组长度16,当元素个数超过 16 x 0.75 = 12时,就会成倍扩容 16 x 2 = 32

HashMap<String, Integer> map = new HashMap<>(32, 0.75f);
  • 通过另一个Map构造
HashMap<String, Integer> map = new HashMap<>(anotherMap);

2.常用方法

  • 添加键值对

插入一个键值对,一个键值对一般称为一个Entity(实体)

如果键已存在,则更新其对应的值

HashMap<String, String> hm = new HashMap<>();
hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
  • 获取值

根据键获取值。如果键不存在,则返回 null

HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
        System.out.println(hm.get("王心妍"));
        System.out.println(hm.get("唐韵"));

  • 检查键是否存在

判断是否包含指定键。

        HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
        System.out.println(hm.containsKey("黄小桃"));
        System.out.println(hm.containsValue("与林逸能打出合击技:狂火合击八卦掌,在金丹初期层面合力击杀过元婴老怪"));

 

  • 删除键值对

删除指定键对应的键值对

        HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
        System.out.println(hm);
        hm.remove("王心妍");
        System.out.println(hm);

  • 获取大小
        HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
        System.out.println(hm.size());

  • 清空所有数据

清空 HashMap 中的所有键值对。

        HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
        System.out.println(hm.size());
        hm.clear();
        System.out.println(hm.size());

  • 获取所有键
        HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "林逸的后宫团中大老婆的有力竞争者之一");
        System.out.println(hm.keySet());

  • 遍历
        HashMap<String, String> hm = new HashMap<>();
        hm.put("王心妍", "是林逸来到松山市见到的第一个女孩");
        hm.put("黄小桃", "是林逸在天阶岛遇到的第二个的青云阁女孩");
        hm.put("王心妍", "是林逸的后宫团中大老婆的有力竞争者之一");
        Set<String> keys = hm.keySet();
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()){
            String item = iterator.next();
            System.out.println(item + hm.get(item));
        }


底层实现

在Java8,HashMap 的底层数据结构是一个数组 + 链表 + 红黑树的组合,主要目的是实现快速的存储和查找。

补充知识点可以我另一篇博客:【JavaSE】基础知识复习(四)-CSDN博客

HashMap 的核心组成部分

  1. 数组(table)

    • HashMap 的核心是一个数组,称为 桶数组,用于存储数据。
    • 每个数组元素称为一个 ,存储链表或红黑树的头结点。
  2. 链表

    • 当多个键的哈希值冲突(计算出相同的索引)时,会将这些键值对存储在一个链表中。
    • 链表长度过长会降低性能(查找时间复杂度为 O(n))。
  3. 红黑树

    • 当链表长度超过某个阈值(默认是 8)时,链表会转化为红黑树。
    • 红黑树的查找时间复杂度为 O(log n),大幅提高了性能。

HashMap 的核心操作流程

1. 插入数据

  • 步骤

    1. 根据 keyhashCode() 计算出哈希值。
    2. 通过 (哈希值 % 数组长度) 计算出数组索引。
    3. 如果桶(数组位置)为空,则直接插入键值对。
    4. 如果桶中有数据(哈希冲突),将新数据追加到链表末尾。如果链表长度超过阈值,则转换为红黑树。
int hash = key.hashCode(); // 计算哈希值
int index = hash % table.length; // 计算数组索引
if (table[index] == null) {
    table[index] = new Node<>(key, value);
} else {
    // 处理哈希冲突,追加到链表或转化为红黑树
}

2. 查询数据

  • 步骤

    1. 根据 keyhashCode() 计算哈希值。
    2. 通过 (哈希值 % 数组长度) 定位到具体的桶。
    3. 遍历桶中的链表或红黑树,查找与 key 匹配的节点。
    4. 返回节点的值。

3. 删除数据

  • 步骤

    1. 根据 key 定位到对应桶。
    2. 遍历链表或红黑树,找到匹配的节点并删除。

扩容机制

1. 扩容条件

HashMap 中的元素个数超过 容量 * 负载因子 时,触发扩容。

  • 默认容量:16。
  • 默认负载因子:0.75。
  • 默认扩容阈值:16 * 0.75 = 12。

2. 扩容过程

  1. 数组容量变为原来的 2 倍。
  2. 重新计算每个键值对的哈希值,移动到新的桶中。

扩容代价较高,因为需要重新计算每个键的哈希值,并将其重新分配到新数组中。


哈希冲突

1. 哈希冲突的原因

不同的键可能会计算出相同的哈希值,导致它们被分配到同一个桶中。

小概率时间,比如下图,就有8亿多个对象的哈希值出现相同现象

2. 解决方法

  • 链表法: 冲突的键值对存储在链表中。
  • 红黑树法: 当冲突较多时,链表转换为红黑树,提高查找效率。

优缺点

优点

  1. 快速查找
    • 理论时间复杂度接近 O(1)。虽然HashMap没有数组那种的直接索引,但是通过计算键的hashCode(),所以理论上查询时间复杂度勉强能赶上数组
  2. 灵活存储
    • 支持键值对存储,可以存储任意类型。
  3. 高效扩容
    • 动态扩容机制提高性能。

缺点

  1. 非线程安全
    • HashMap 不是线程安全的,多个线程同时操作可能导致数据不一致。
    • 解决方案:使用 ConcurrentHashMapCollections.synchronizedMap
  2. 扩容代价高
    • 扩容会导致性能短暂下降,适合频繁读取但写入次数较少的场景。

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

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

相关文章

windwos defender实现白名单效果(除了指定应用或端口其它一律禁止)禁止服务器上网

一、应用场景说明 当我们的一台windows服务器中毒&#xff0c;变成别人肉鸡&#xff0c;不断向外请示非法网站或攻击其它服务器。 要彻底清除相关木马或病毒往往需要的时间比较长&#xff0c;比较有效的方法是禁止服务器主动向外发包除了网站端口和远程程序除外。 其实这就是一…

免费送源码:Java+ssm++MVC+HTML+CSS+MySQL springboot 社区医院信息管理系统的设计与实现 计算机毕业设计原创定制

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设社区医院信息管理系统…

AI的进阶之路:从机器学习到深度学习的演变(四)

AI的进阶之路&#xff1a;从机器学习到深度学习的演变&#xff08;三&#xff09; 五、深度学习的应用领域 深度学习的应用领域广泛&#xff0c;涵盖了计算机视觉、自然语言处理、语音识别和推荐系统等多个方面。以下将详细探讨这些关键应用领域&#xff0c;展示深度学习在不同…

electron-vite【实战】自定义标题栏【组件封装】(含异形标题栏,指定区域拖拽,窗口置顶,窗口最小化,窗口最大化,取消最大化,隐藏窗口到托盘等)

效果预览 技术要点 透明背景 src/main/index.ts 的 new BrowserWindow 中添加 transparent: true, // 设置窗口背景透明frame: false, // 隐藏窗口边框仅图标和标题部分可拖拽 仅图标和标题部分添加样式 drag .drag {-webkit-app-region: drag; }图标与标题栏的融合 标题栏的…

[react] 获取ant组件ref用ts如何定义?

获取ant的轮播图组件, 我用ts如何定义? import React, { ElementRef } from react; const lunboRef useRef<ElementRef<typeof Carousel>>(null); <Carousel autoplay ref{lunboRef}> 这样就行了! ,然后点一下看看.弹出提示了 当然你还可以用ant内置的G…

springboot中Controller内文件上传到本地以及阿里云

上传文件的基本操作 <form action"/upload" method"post" enctype"multipart/form-data"> <h1>登录</h1> 姓名&#xff1a;<input type"text" name"username" required><br> 年龄&#xf…

python 曲线拟合,曲线拟合交点

目录 效果图: 源代码: 效果图: 源代码: import json import os import shutilimport cv2 import numpy as npfrom numpy.polynomial.polynomial import Polynomialdef calculate_distance(x1, y1, x2, y2):return np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)def get_new_g…

java 集合对象

Java 基础之集合_java集合继承关系图-CSDN博客 集合可以有序或无序&#xff0c;重复或不能重复&#xff0c;空或不能空。 List<> 集合&#xff0c;是有序&#xff0c;允许重复元素&#xff0c;允许空元素 1、ArrayList<> 非线程安全 2、LInkedList<> 非线…

【零基础学习UDS诊断测试】——0x27测试用例设计

从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者,时光不负有心人。 目录 1.概述 2.响应情况 3.测试点解析 4.0x27诊断调查表 5.详细用例展示 1.概述 UDS(统一诊断服务)中的0x27服务,即安全访问服务(Security Access Service),其主要作用…

【BUG记录】Apifox 参数传入 + 号变成空格的 BUG

文章目录 1. 问题描述2. 原因2.1 编码2.2 解码 3. 解决方法 1. 问题描述 之前写了一个接口&#xff0c;用 Apifox 请求&#xff0c;参数传入一个 86 的电话&#xff0c;结果到服务器 就变成空格了。 Java 接收请求的接口&#xff1a; 2. 原因 2.1 编码 进行 URL 请求的…

视频直播点播平台EasyDSS推拉流技术结合无人机推流在道路交通巡检场景中的应用

随着城市化进程的加速&#xff0c;交通网络日益复杂&#xff0c;交通巡检工作面临着前所未有的挑战。传统的巡检方式往往依赖于人工巡查或地面监控设备&#xff0c;但这些方法存在巡检范围有限、效率低下等缺点。 无人机凭借其高空视野、灵活机动、实时监控等优势&#xff0c;…

git仓库的基本概念和流程以及一些基本命令

什么是版本库&#xff1f;版本库又名仓库&#xff0c;英文名repository,你可以简单的理解一个目录&#xff0c;这个目录里面的所有文件都可以被Git管理起来&#xff0c;每个文件的修改&#xff0c;删除&#xff0c;Git都能跟踪&#xff0c;以便任何时刻都可以追踪历史&#xff…

2025erp系统开源免费进销存系统搭建教程/功能介绍/上线即可运营软件平台源码

系统介绍 基于ThinkPHP与LayUI构建的全方位进销存解决方案 本系统集成了采购、销售、零售、多仓库管理、财务管理等核心功能模块&#xff0c;旨在为企业提供一站式进销存管理体验。借助详尽的报表分析和灵活的设置选项&#xff0c;企业可实现精细化管理&#xff0c;提升运营效…

2024技能大赛Vue流程复现

1. 关于版本的控制 vue/cli 5.0.8vscode 最新下载版本 2. 创建vuecli项目 若没有安装vuecli则可以先安装 npm install -g vue/cli # 默认下载最新版本。vue --version vue -V # 查看版本&#xff0c;两个选一 使用vuecli来创建一个新的vue项目&#xff0c;vs code打开…

Qwen2.5-7B-Instruct FastApi部署与调用

Qwen2.5-7B-Instruct FastApi 部署调用 环境准备 本文基础环境如下&#xff1a; ---------------- ubuntu 22.04 python 3.12 cuda 12.1 pytorch 2.3.0 ----------------本文默认学习者已安装好以上 Pytorch(cuda) 环境&#xff0c;如未安装请自行安装。 首先 pip 换源加速下…

【Vue3学习】ref,reactive,toRef,toRefs的功能与用法区别

在 Vue 3 的组合式 API&#xff08;Composition API&#xff09;中&#xff0c;ref、reactive、toRef 和 toRefs 是四个非常重要的工具函数&#xff0c;用于创建和管理响应式数据。 一、ref 用ref()包裹数据,返回的响应式引用对象&#xff0c;包含一个 .value 属性&#xff0…

【面试 - 遇到的问题】Vue 里 router-view 使用 key + 关闭页面后重新打开页面-获取的数据赋值到旧组件问题(钩子执行顺序)

目录 【1】问题描述【2】问题排查前 - 页面渲染、tag 页签渲染 逻辑梳理页面渲染【借用别人的描述】<router-view :key"key" />1. 不设置key 属性2. 设置 key 属性值为 $route.path/page/1 > /page/2/page?id1 > /page?id2, 3. 设置 key 属性值为 $rou…

电商商品详情API接口(item get)数据分析上货

电商商品详情API接口&#xff08;item get&#xff09;在数据分析与商品上货方面发挥着重要作用。以下是对这两个方面的详细探讨&#xff1a; 一、数据分析 数据源获取&#xff1a; 商品详情API接口提供了丰富的数据源&#xff0c;包括商品的标题、价格、库存、描述、图片、用…

【计算机网络】期末考试预习复习|中

作业讲解 转发器、网桥、路由器和网关(4-6) 作为中间设备&#xff0c;转发器、网桥、路由器和网关有何区别&#xff1f; (1) 物理层使用的中间设备叫做转发器(repeater)。 (2) 数据链路层使用的中间设备叫做网桥或桥接器(bridge)。 (3) 网络层使用的中间设备叫做路…

大数据与AI:从分析到预测的跃迁

引言&#xff1a;数据时代的新纪元 从每天的社交分享到企业的运营决策&#xff0c;数据早已成为现代社会不可或缺的资源。我们正置身于一个数据爆炸的时代&#xff0c;数以亿计的信息流实时生成&#xff0c;为人类带来了前所未有的洞察能力。然而&#xff0c;数据的价值并不仅限…