【数据结构】哈希表详解,举例说明 java中的 HashMap、HashTable及其区别

news/2025/1/3 6:32:37/

一、哈希表(Hash Table)简介:

哈希表是一种数据结构,用于实现字典或映射等抽象数据类型。它通过把关键字映射到表中的一个位置来实现快速的数据检索。哈希表的基本思想是利用哈希函数将关键字映射到数组的索引位置上,从而实现常数时间的查找、插入和删除操作

二、哈希表的基本组成部分:

在这里插入图片描述

  • 哈希函数(Hash Function): 哈希函数负责将关键字映射到哈希表的索引位置。一个好的哈希函数应该能够将关键字均匀地分布到哈希表的各个位置上,减少冲突的概率。
  • 数组(Array): 哈希表的主要存储结构是一个数组,通过哈希函数计算的索引将关键字映射到数组的位置上。
  • 冲突处理(Collision Resolution): 冲突是指两个不同的关键字被哈希函数映射到了相同的位置上。常见的冲突处理方法包括链地址法和开放地址法。
  • 链地址法(Separate Chaining): 每个哈希表的位置上维护一个链表,冲突的关键字被放入相应位置的链表中。如上图所示,是一个链地址法实现的哈希表。
  • 开放地址法(Open Addressing):如果发生冲突,就尝试寻找下一个可用的位置。有多种开放地址法的实现方式,如线性探测、二次探测等。

三、Java 中的 HashMap:

在 Java 中,HashMap 是基于哈希表实现的键值对存储的数据结构。以下是 HashMap 的一些重要特性和实现细节:

  • 数据结构: HashMap 使用数组存储键值对,每个数组元素称为桶(bucket)。每个桶可以存储多个键值对。
  • 哈希函数: HashMap 使用键的哈希码来确定桶的位置。Java 中的 hashCode() 方法用于获取对象的哈希码。
  • 冲突处理: 当多个键的哈希码映射到相同的桶上时,HashMap 使用链地址法或者红黑树来解决冲突,即在桶中维护一个链表。
  • 负载因子和扩容: HashMap 有一个负载因子(load factor)的概念,当桶中的键值对数量达到负载因子与桶的容量的乘积时,触发扩容操作。默认负载因子为 0.75。负载因子的值增大,冲突率也随着增大,我们不能直接控制冲突率,可以通过影响负载因子来降低冲率,而控制负载因子,负载因子是哈希表的元素数量除哈希桶数量,我们认为哈希表要传入的数量是未知的,也可以看作无穷的,所以,通过不能降低减少哈希表元素的数量来降低负载因子的值,但我们可以通过增加哈希桶的值来降低负载因子的值,进而降低冲突率。
  • 迭代顺序: HashMap 的迭代顺序不是固定的,不同版本的 JDK 可能有不同的实现。在 Java 8 之前,HashMap 的迭代顺序是不确定的。在 Java 8 及以后,为了提高性能,引入了红黑树(RB-tree)来优化链表,影响了迭代顺序。
  • 线程安全: HashMap 不是线程安全的,如果多个线程同时操作 HashMap,可能会导致并发问题。可以考虑使用 Collections.synchronizedMap() 或者 ConcurrentHashMap 来实现线程安全。参考【数据类型】ConcurrentHashMap分段锁实现高并发 和【数据类型】Collections.synchronizedMap 多线程Map
// 示例代码
import java.util.HashMap;
import java.util.Map;public class HashMapExample {public static void main(String[] args) {// 创建 HashMap 实例Map<String, Integer> hashMap = new HashMap<>();// 添加键值对hashMap.put("Alice", 25);hashMap.put("Bob", 30);hashMap.put("Charlie", 22);// 获取值int age = hashMap.get("Bob");System.out.println("Bob's age: " + age);// 遍历 HashMapfor (Map.Entry<String, Integer> entry : hashMap.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());}}
}

上述代码展示了使用 HashMap 存储和访问键值对的基本操作。

四、java中的HashTable

HashTable也是利用哈希表算法原理,Hashtable底层也采用数组+链表的数据结构进行实现,当哈希冲突发生时,使用链表来解决冲突。与HashMap不同的是,Hashtable在JDK 8及以前没有使用红黑树解决哈希冲突,这导致了其效率相对较低。还有以下几处不同:

1、同步性:

  • HashTable: 是线程安全的,所有的方法都是同步的,即在单个方法调用时,HashTable 会对其进行锁定,以确保线程安全。这使得在并发环境下,HashTable 是安全的,但在性能上可能会受到影响。
  • HashMap: 不是线程安全的。在多线程环境下,如果没有外部同步措施,对 HashMap 进行并发修改可能导致不确定的结果。

2、空值处理:

  • HashTable: 不允许键或值为 null,如果试图存储 null 键或值,会抛出 NullPointerException。
  • HashMap: 允许键和值为 null。

3、继承关系:

  • Hashtable 继承自Dictionary类,Dictionary类是一个已经被废弃的类(见其源码中的注释)。父类都被废弃,自然而然也没人用它的子类Hashtable了。
  • HashMap 继承自AbstractMap类,是 Java Collections Framework 中的一部分。但二者都实现了Map接口。

4、性能:

  • 由于 HashTable 在所有方法上使用同步,它在性能上可能会受到影响,尤其在多线程环境下。
  • HashMap 不使用同步,因此在单线程环境或者不需要线程安全保证的场景下,性能可能更好。

在新的 Java 5+ 版本中,推荐使用 HashMap 或者 ConcurrentHashMap 而不是
HashTable,因为它们提供了更好的性能和更灵活的使用方式。

5、包含的contains方法不同

  • hashtable则保留了 contains 方法,效果同 containsValue ,还包括 containsValue 和 containsKey 方法。
  • HashMap是没有 contains 方法的,而包括 containsValue 和 containsKey 方法.

6、应用场景

根据上述的区别和特点,我们可以得出以下建议:

  • 如果线程安全的Map集合,并且不需要存储null键或null值,可以选择Hashtable
  • 如果需要高效、非线程安全的Map集合,并且需要存储null键或null值,可以选择HashMap
  • 如果需要高效、线程安全的Map集合,可以选择使用ConcurrentHashMap,也允许键、值为null

知识是一个环,来我的博客绕圈吧~ 持续更新中,后续更精彩!


http://www.ppmy.cn/news/1323395.html

相关文章

PHP AES加密:保护数据安全的高级加密技术

PHP AES加密&#xff1a;保护数据安全的高级加密技术 ASE&#xff08;Advanced Encryption Standard&#xff09;是一种对称加密算法&#xff0c;也被称为Rijndael加密算法。它是由比利时密码学家Joan Daemen和Vincent Rijmen设计的&#xff0c;于2001年被美国国家标准与技术研…

深度系统QT 环境搭建

1.QT安装 不折腾最新版直接去商店搜索QT安装。 2.修改su密码&#xff0c;安装需要权限 打开一个终端&#xff0c;然后输入下面的命令&#xff1a;按照提示输入密码按回车就行。 sudo passwd 回车后会出现让你输入现在这个账户的密码&#xff1a; 3.编译环境安装。 安…

GPT实战系列-简单聊聊LangChain搭建本地知识库准备

GPT实战系列-简单聊聊LangChain搭建本地知识库准备 LangChain 是一个开发由语言模型驱动的应用程序的框架&#xff0c;除了和应用程序通过 API 调用&#xff0c; 还会&#xff1a; 数据感知 : 将语言模型连接到其他数据源 具有代理性质 : 允许语言模型与其环境交互 LLM大模型…

学习JavaEE的日子 day13 封装 static private this 类加载机制

Day13 1. private – 私有化 理解&#xff1a;private是访问修饰符的一种&#xff0c;访问修饰符规定了访问权限. 作用&#xff1a; ​ 1.private修饰属性&#xff1a;该属性只能在类的内部使用 ​ 2.private修饰方法&#xff1a;该方法只能在类的内部使用 应用场景&#xff1…

第三章 计算机网络技术基础——教案(附PPT)

第三章 计算机网络技术基础 一、教学目标: 1. 掌握几种常见网络拓扑结构的原理及其特点 2. 掌握ISO/OSI网络参考模型及各层的主要功能 3. 掌握共享介质方式的CSMA/CD和令牌传递两种数据传输控制方式的基本原理 4. 了解几种常见的网络类型 5. 掌握TCP/IP协议的层次结构及…

利用docker的LNMP

目录 服务器环境 任务需求 服务搭建 Nginx Mysql Php 启动 wordpress 服务 服务器环境 容器 操作系统 IP地址 主要软件 nginx CentOS 7 172.20.0.10 Docker-Nginx mysql CentOS 7 172.20.0.20 Docker-Mysql php CentOS 7 172.2…

java日志框架总结

一、日志框架简单分类介绍 java常用的日志框架、可以分为两组&#xff1a; 1、JCL、JUL、Log4j&#xff1b; 2、SLF4J、Log4j2、Logback&#xff1b; 其中第一组是比较早期的日志实现框架&#xff0c;JCL并不是具体的日志实现框架&#xff0c;JCL其实是定义了一…

Vue实战:两种方式创建Vue项目

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;安装Vue CLI脚手架1、从Node.js官网下载LTS版本2、安装Node.js到指定目录3、配置Node.js环境变量4、查看node版本5、查看npm版本6、安装Vue Cli脚手架7、查看Vue Cli版本 &#xff08;二&#xff09;命令行方式构建…