容器四(Map 接口)

news2024/11/27 6:24:27

      

目录

HashMap 和 HashTable

Map 接口中的常用方法

HashMap 底层实现

Hashmap 基本结构

存储数据过程 put(key,value)

取数据过程 get(key)

扩容问题

JDK8 将链表在大于 8 情况下变为红黑二叉树


        Map 就是用来存储“键(key)-值(value) 对”的。 Map 类中存储的“键值对”通过键来标 识,所以“键对象”不能重复。

        Map 接口的实现类有 HashMap、TreeMap、HashTable、Properties 等。

Map 接口中常用的方法
方法说明
Object put(Object key, Object value)存放键值对
Object get(Object key)通过键对象查找得到值对象
Object remove(Object key)删除键对象对应的键值对
boolean containsKey(Object key)Map 容器中是否包含键对象对应的键值对
boolean containsValue(Object value)Map 容器中是否包含值对象对应的键值对
int size()包含键值对的数量
boolean isEmpty()Map 是否为空
void putAll(Map t)将 t 的所有键值对存放到本 map 对象
void clear()清空本 map 对象所有键值对

HashMap 和 HashTable

        HashMap 采用哈希算法实现,是 Map 接口最常用的实现类。 由于底层采用了哈希表存 储数据,我们要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。 HashMap 在查找、删除、修改方面都有非常高的效率。

Map 接口中的常用方法

import java.util.HashMap;
import java.util.Map;

public class TestMap {
    public static void main(String[ ] args) {
        Map<Integer, String> m1 = new HashMap<Integer, String>();
        Map<Integer, String> m2 = new HashMap<Integer, String>();
        m1.put(1, "one");
        m1.put(2, "two");
        m1.put(3, "three");
        m2.put(1, "一");
        m2.put(2, "二");
        System.out.println(m1.size());
        System.out.println(m1.containsKey(1));
        System.out.println(m2.containsValue("two"));
        m1.put(3, "third"); //键重复了,则会替换旧的键值对
        Map<Integer, String> m3 = new HashMap<Integer, String>();
        m3.putAll(m1);
        m3.putAll(m2);
        System.out.println("m1:" + m1);
        System.out.println("m2:" + m2);
        System.out.println("m3:" + m3);
    }
}

        HashTable 类和 HashMap 用法几乎一样,底层实现几乎一样,只不过 HashTable 的方法添加了 synchronized 关键字确保线程同步检查,效率较低。

HashMap 与 HashTable 的区别

HashMap: 线程不安全,效率高。允许 key 或 value 为 null。

HashTable: 线程安全,效率低。不允许 key 或 value 为 null。

HashMap 底层实现

        HashMap 底层实现采用了哈希表,这是一种非常重要的数据结构。

        数据结构中由数组和链表来实现对数据的存储,他们各有特点。

(1) 数组:占用空间连续。 寻址容易,查询速度快。但是,增加和删除效率非常低。

(2) 链表:占用空间不连续。 寻址困难,查询速度慢。但是,增加和删除效率非常高。

能结合数组和链表的优点(即查询快,增删效率也高),也就是“哈希表”。

哈希表的本质就是“数组+链表”。

Hashmap 基本结构

HashMap 源码,有如下两个核心内容:

其中的 Node[K, V ] table 就是 HashMap 的核心数组结构,我们也称之为“位桶数组”。

Node[K, V ] 源码为: 

一个 Node 对象存储了:

  • key:键对象   value:值对象
  • next:下一个节点
  • hash: 键对象的 hash 值

显然每一个 Node 对象就是一个单向链表结构

画出 Node[ ]数组的结构(这也是 HashMap 的结构):

存储数据过程 put(key,value)

        HashMap 如何存储数据呢?其核心是如何产生 hash 值,该值用来对应数组的存储位置。

测试 hash 算法

public class TestMap {
    public static void main(String[ ] args) {
        int h = 25860399;
        int length = 16;//length为2的整数次幂,则h&(length-1)相当于对length取模
        myHash(h, length);
    }

    /**
     *
     * @param h 任意整数
     * @param length 长度必须为2的整数幂
     * @return
     */
    public static int myHash(int h,int length){
        System.out.println(h&(length-1));
        //length为2的整数幂情况下,和取余的值一样
        System.out.println(h%length);//取余数
        return h&(length-1);
    }
}

        能发现直接取余(h%length)和位运算(h&(length-1))结果是一 致的。事实上,为了获得更好的散列效果,JDK 对 hashcode 进行了两次散列处理(核心目标就是为了分布更散更均匀)

        当添加一个元素(key-value)时,首先计算 key 的 hash 值,以此确定插入数组中的位 置,但是可能存在同一 hash 值的元素已经被放在数组同一位置了,这时就添加到同一 hash 值的元素的后面,他们在数组的同一位置,就形成了链表,同一个链表上的 Hash 值是相同 的,所以说数组存放的是链表。 JDK8 中,当链表长度大于 8 时,链表就转换为红黑树, 这样又大大提高了查找的效率。

取数据过程 get(key)

        需要通过 key 对象获得“键值对”对象,进而返回 value 对象。

(1) 获得 key 的 hashcode,通过 hash()散列算法得到 hash 值,进而定位到数组的位置。

(2) 在链表上挨个比较 key 对象。 调用 equals()方法,将 key 对象和链表上所有节点的 key 对象进行比较,直到碰到返回 true 的节点对象为止。

(3) 返回 equals()为 true 的节点对象的 value 对象。

        Java 中规定,两个内容相同(equals()为 true)的对象必须具有相等的 hashCode。因为如果 equals()为 true 而两个对象的 hashcode 不同;那在整个存储过程中就发生了悖论。

扩容问题

        HashMap 的位桶数组,初始大小为 16。实际使用时,显然大小是可变的。如果位桶数 组中的元素达到(0.75*数组 length), 就重新调整数组大小变为原来 2 倍大小。

        扩容很耗时。扩容的本质是定义新的更大的数组,并将旧数组内容挨个拷贝到新数组中。

JDK8 将链表在大于 8 情况下变为红黑二叉树

        JDK8 中,HashMap 在存储一个元素时,当对应链表长度大于 8 时,链表就转换为红黑 树,这样又大大提高了查找的效率。

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

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

相关文章

《科技创新与应用》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答&#xff1a; 问&#xff1a;《科技创新与应用》是什么级别期刊&#xff1f; 答&#xff1a;省级&#xff1b;主管单位&#xff1a;黑龙江省科学技术协会&#xff1b;主办单位&#xff1a;黑龙江省创联文化传媒有限公司 问&#xff1a;《科技创新与应用》是核心期刊…

链游系统开发运营版丨链游系统开发指南教程

在当今数字经济时代&#xff0c;区块链技术的发展不仅改变了金融行业&#xff0c;也深刻影响了游戏产业。链游系统&#xff08;Blockchain Game System&#xff09;作为区块链技术与游戏行业的结合&#xff0c;正在成为新一代游戏的趋势。本文将为您详细介绍链游系统的开发与运…

2024年【N1叉车司机】考试技巧及N1叉车司机复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 N1叉车司机考试技巧参考答案及N1叉车司机考试试题解析是安全生产模拟考试一点通题库老师及N1叉车司机操作证已考过的学员汇总&#xff0c;相对有效帮助N1叉车司机复审考试学员顺利通过考试。 1、【多选题】《中华人民…

南京观海微电子---Vitis HLS的工作机制——Vitis HLS教程

1. 前言 Vitis HLS&#xff08;原VivadoHLS&#xff09;是一个高级综合工具。用户可以通过该工具直接将C、 C编写的函数翻译成HDL硬件描述语言&#xff0c;最终再映射成FPGA内部的LUT、DSP资源以及RAM资源等。 用户通过Vitis HLS&#xff0c;使用C/C代码来开发RTL IP核&#x…

思通数科:利用开源AI能力引擎平台打造企业智能搜索系统

在信息爆炸的时代&#xff0c;如何高效地管理和检索海量数据已成为企业和个人面临的一大挑战。思通数科 StoneDT 多模态AI能力引擎平台&#xff0c;以其强大的自然语言处理&#xff08;NLP&#xff09;、OCR识别、图像识别和文本抽取技术&#xff0c;为用户带来了前所未有的智能…

第N6周:使用Word2vec实现文本分类

import torch import torch.nn as nn import torchvision from torchvision import transforms,datasets import os,PIL,pathlib,warnings #忽略警告信息 warnings.filterwarnings("ignore") # win10系统 device torch.device("cuda"if torch.cuda.is_ava…

深入探索Yarn:安装与使用指南

Yarn 是一个由 Facebook 开发的 JavaScript 包管理器&#xff0c;旨在提供更快、更可靠的包管理体验。它与 npm 类似&#xff0c;但在某些方面更加高效和可靠。本文将介绍如何安装 Yarn&#xff0c;并展示如何使用它来管理 JavaScript 项目的依赖。 1. 安装 Yarn Yarn 可以通…

vs2022 关于Python项目无法识别中文的解决方法

这是针对于vs2022安装和使用教程&#xff08;详细&#xff09;-CSDN博客 Python项目无法识别中文的解决方法的文章 一、问题 1.输入代码 print("你好Hello world&#xff01;") 2.启动&#xff0c;发现代码里有中文报错 二、解决方法 1.选择菜单栏里的工具->…

阿里云服务器ECS经济型e和u1实例规格如何选择?

阿里云服务器u1和e实例有什么区别&#xff1f;ECS通用算力型u1实例是企业级独享型云服务器&#xff0c;ECS经济型e实例是共享型云服务器&#xff0c;所以相比较e实例&#xff0c;云服务器u1性能更好一些。e实例为共享型云服务器&#xff0c;共享型实例采用非绑定CPU调度模式&am…

线程的等待通知机制

线程的等待通知机制 一:情景再现:二:等待通知机制:2.1 wait()方法2.2 notify()方法2.22:唤醒了t2线程,t1线程仍处于阻塞等待状态2.23 唤醒了t1线程,t2线程仍处于阻塞等待状态2.24:notifyAll() 一:情景再现: 假设有3个滑稽,1号滑稽在ATM中取钱,2,3号滑稽只能在门口阻塞等待,1号…

VuePress基于 Vite 和 Vue 构建优秀框架

VitePress 是一个静态站点生成器 (SSG)&#xff0c;专为构建快速、以内容为中心的站点而设计。简而言之&#xff0c;VitePress 获取用 Markdown 编写的内容&#xff0c;对其应用主题&#xff0c;并生成可以轻松部署到任何地方的静态 HTML 页面。 VitePress 附带一个用于技术文档…

Vmware下减小Ubuntu系统占用系统盘大小

1、虚拟机设置下占用空间 如图&#xff0c;给虚拟机分配了120GB&#xff0c;已经占用116.9GB&#xff0c;开机会提示空间不足。 2、实际使用空间 ubuntu系统下使用“df -h”命令查看实际使用空间大小50GB左右 造成这个原因是&#xff0c;虚拟机的bug&#xff1a;在虚拟机的ub…

【递归】有序分数(SBT)

给定一个整数 N&#xff0c;请你求出所有分母小于或等于 N&#xff0c;大小在 [0,1][0,1] 范围内的最简分数&#xff0c;并按从小到大顺序依次输出。 例如&#xff0c;当 N5时&#xff0c;所有满足条件的分数按顺序依次为&#xff1a; 0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4…

二叉树寻找祖先问题-算法通关村

二叉树寻找祖先问题-算法通关村 1 最近公共祖先问题 LeetCode236&#xff1a;给定一个二叉树&#xff0c;找到该树中两个指定节点的最近公共祖先。 最近公共祖先的定义为&#xff1a;“对于有根树T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足是…

Docket常见的软件部署1

1 安装MySQL # 查看MySQL镜像 docker search mysql # 拉起镜像 docker pull mysql:5.7 # 创建MySQL数据映射卷&#xff0c;防止数据不丢失 mkdir -p /hmoe/tem/docker/mysql/data/ # 启动镜像 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -v /home…

7_springboot_shiro_jwt_多端认证鉴权_自定义AuthenticationToken

1. 目标 ​ 本小节会先对Shiro的核心流程进行一次回顾&#xff0c;并进行梳理。然后会介绍如果应用是以API接口的方式提供给它方进行调用&#xff0c;那么在这种情况下如何使用Shiro框架来完成接口调用的认证和授权。 2. 核心架构 引用官方的架构图&#xff1a; 2.1 Subje…

蓝桥杯第十五届抱佛脚(八)并查集

蓝桥杯第十五届抱佛脚&#xff08;八&#xff09;并查集 基本概念 并查集是一种数据结构&#xff0c;用于管理一系列不交集的元素集合&#xff0c;并支持两种操作&#xff1a; 查找&#xff08;Find&#xff09;&#xff1a; 查找操作用于确定某个元素属于哪个集合&#xf…

Topaz Photo AI for Mac v2.4.2 智能AI降噪软件

Topaz Photo AI是一款适用于Mac的图像处理软件&#xff0c;使用人工智能技术对照片进行编辑和优化。该软件提供了多种强大的功能&#xff0c;包括降噪、锐化、消除噪点、提高分辨率等&#xff0c;可以帮助用户改善图像质量&#xff0c;并实现自定义的效果。 软件下载&#xff1…

前端-html-02

1.列表 标签名功能和语义属性单标签还是双标签ul无序列表包裹元素双标签 ol 有序列表包裹元素双标签li列表项双标签dl定义列表包裹元素双标签dt定义列表项标题双标签dd定义列表项描述双标签 li必须由Ul或者ol包裹 <!DOCTYPE html> <html><head><…

Web APIs知识点讲解(阶段七)

正则表达式 1.能够利用正则表达式校验输入信息的合法性2. 具备利用正则表达式验证小兔鲜注册页面表单的能力 一.正则表达式 1.正则表达式 正则表达式&#xff08;Regular Expression&#xff09;是用于匹配字符串中字符组合的模式。在 JavaScript中&#xff0c;正则表达式也…