首页 > 编程语言 >探索 Java 中的 HashMap

探索 Java 中的 HashMap

时间:2024-12-28 11:29:57浏览次数:7  
标签:map Java HashMap 探索 Alice 键值 哈希 Bob

在 Java 的开发中,HashMap 是一个非常常用且重要的数据结构。它实现了 Map 接口,以键值对 (key-value pair) 的形式存储数据,并通过 哈希表 (Hash Table) 来实现高效的存储和查找。

本文将深入探讨 HashMap 的核心功能、使用场景、底层原理和注意事项。


1. 什么是 HashMap?

HashMap 是 Java 集合框架中的一个类,位于 java.util 包下。它是一个 无序的键值对集合,主要特点如下:

  • 基于哈希表,可以快速插入、删除和查找。
  • 键不能重复,但值可以重复。
  • 允许 null 值,即键和值都可以为 null
  • 非线程安全,多个线程操作需要额外的同步。

HashMap 的常见用途:

  1. 存储和快速查找数据,例如缓存数据。
  2. 实现关联数组或字典。
  3. 用作键值对存储的中间结构,例如统计字符频率。

2. HashMap 的基本操作

创建一个 HashMap

在 Java 中,可以通过以下方式创建 HashMap

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        // 创建一个 HashMap
        HashMap<String, Integer> map = new HashMap<>();
        
        // 添加键值对
        map.put("Alice", 25);
        map.put("Bob", 30);
        map.put("Charlie", 35);
        
        // 输出 HashMap
        System.out.println(map);
    }
}

输出示例:

{Alice=25, Bob=30, Charlie=35}

常见方法:

方法作用
put(K key, V value)添加或更新键值对
get(Object key)根据键获取对应的值
containsKey(Object key)判断是否包含某个键
containsValue(Object value)判断是否包含某个值
remove(Object key)删除指定键及其对应的值
size()返回键值对的数量
isEmpty()判断 HashMap 是否为空
keySet()返回所有键的集合(Set 类型)
values()返回所有值的集合(Collection 类型)
entrySet()返回所有键值对的集合(Set<Map.Entry<K,V>> 类型)

示例代码:

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();

        // 添加元素
        map.put("Alice", 25);
        map.put("Bob", 30);
        map.put("Charlie", 35);

        // 获取元素
        System.out.println("Bob's age: " + map.get("Bob"));

        // 判断是否存在键和值
        System.out.println("Contains key 'Alice': " + map.containsKey("Alice"));
        System.out.println("Contains value 30: " + map.containsValue(30));

        // 遍历 HashMap
        System.out.println("All entries:");
        for (var entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }

        // 删除元素
        map.remove("Charlie");
        System.out.println("After removing Charlie: " + map);
    }
}

展开

输出:

Bob's age: 30
Contains key 'Alice': true
Contains value 30: true
All entries:
Alice = 25
Bob = 30
Charlie = 35
After removing Charlie: {Alice=25, Bob=30}

3. HashMap 的底层原理

HashMap 的高效性来自其底层的 哈希表 (Hash Table) 实现。了解其底层原理有助于更好地掌握它的使用场景和限制。

3.1 存储结构

  • HashMap 底层是一个 数组,数组的每个位置存储一个 链表(JDK 1.7)或红黑树(JDK 1.8)
  • 数组中的每个位置被称为 桶 (Bucket)

3.2 存储过程

  1. 计算键的哈希值
    使用键的 hashCode() 方法计算哈希值,然后通过哈希函数将其映射到数组的某个位置。

    index = hash(key) % arrayLength;
    
  2. 解决哈希冲突

    • 如果两个键映射到同一个桶,就会发生哈希冲突。
    • JDK 1.7 使用链表解决冲突,冲突的键值对会被存储在链表的节点中。
    • JDK 1.8 引入了红黑树,当链表长度超过 8 时,链表会转换为红黑树以提高性能。
  3. 扩容
    当 HashMap 中的键值对数量超过阈值(默认是桶大小的 0.75),HashMap 会扩容为原来的两倍,并重新分配键值对的位置。


3.3 示例:存储原理

以下示例展示了 HashMap 的底层原理:

HashMap<String, Integer> map = new HashMap<>();
map.put("Alice", 25); // 哈希值映射到桶1
map.put("Bob", 30);   // 哈希值映射到桶2
map.put("Eve", 35);   // 哈希值映射到桶1,与 "Alice" 发生冲突

存储结构如下:

Bucket 0: null
Bucket 1: Alice -> Eve
Bucket 2: Bob
Bucket 3: null

当链表过长(长度 > 8)时:

Bucket 1: Alice -> Eve (链表转为红黑树)

4. HashMap 的优缺点

优点:

  1. 快速访问:通过哈希表实现,时间复杂度为 O(1)(理想情况下)。
  2. 灵活性:允许 null 键和值,支持动态扩容。
  3. 丰富的 API:操作简便。

缺点:

  1. 线程不安全:需要手动同步(例如使用 Collections.synchronizedMap() 或 ConcurrentHashMap)。
  2. 空间占用高:为了减少冲突,HashMap 通常会预留更多空间。

5. HashMap 的注意事项

  1. 线程安全性:在多线程环境中,使用 ConcurrentHashMap 代替 HashMap
  2. 哈希函数设计:避免过多的哈希冲突,以提升性能。
  3. 迭代期间修改:不要在遍历 HashMap 时修改其内容,否则会抛出 ConcurrentModificationException

6. 小结

HashMap 是 Java 中最重要的数据结构之一,其高效性和灵活性使其在各种应用中大放异彩。然而,掌握其底层原理和适用场景至关重要。通过合理使用 HashMap,可以大大提升程序的性能和可维护性。

希望本文能帮助你更好地理解和使用 HashMap!如果你有其他问题或补充,欢迎留言讨论!

标签:map,Java,HashMap,探索,Alice,键值,哈希,Bob
From: https://blog.csdn.net/q68686/article/details/144785582

相关文章

  • [Java SE] 核心源码精讲:java.net.URLConnection
    概述:URLConnectionURLConnection是一个抽象类,表示指向URL【指定资源】的活动连接URLConnection可以检查服务器发送的首部,并相应地做出响应。它可以设置客户端请求中使用的首部字段。URLConnection可以用POST、PUT和其他HTTP请求方法向服务器发回数据;URLConnection类是J......
  • java中各种字符编码通过字节向16进制的互转:UTF8|GBK|unicode 字符串<=>字节<=>16进制字符
    文章目录引言I16进制、字节、编码字符之间的转换前提16进制格式字符串‌16进制格式字符串的应用场景转换原理转换流程:字符串<=>字节<=>16进制java中编码的转换APIII其他例子TCP协议字段编码基于netty实现TCP的编码设置将16进制字符串转换为字符串......
  • 基于Java的博物馆数字化网络平台
    计算机毕业设计案例Java毕业设计案例ASP.NET毕业设计案例PHP毕业设计案例微信小程序毕业设计案例基于Java的小程序自习室预约管理系统JavaSpringboot智能膳食咨询系统【12/15/02】ThinkPHP实验教学管理系统–2024计算机毕业设计Java物业管理小程序的设计与实现基于Java的......
  • java核心基础 第六章 锁
    在现实生活中,人们对锁的期望是,它能对某些事物形成一个屏障,除了上锁者外,谁也不能碰到这些事物。比如我在大街上看见了一块金子,我立刻拿来一个透明箱子,把这块金子放在箱子里然后把这个箱子锁上。假设这个箱子和锁都是绝对坚固的,只有我能打开。这个时候走在大街上的人们无论多想得......
  • javaWeb开发
    JavaWeb开发作为软件开发领域的一个重要分支,已经历经数十年的发展,并凭借其强大的跨平台能力、丰富的生态系统以及高度的安全性,成为构建企业级应用的首选技术之一。以下是对JavaWeb开发的详细解析:一、JavaWeb开发的基本概念JavaWeb开发是指使用Java语言及其相关技术栈......
  • [VUE]CALL_AND_RETRY_LAST分配失败-JavaScript堆内存不足 errno134
    使用vscode开发项目,由于项目较大,在运行npmrundev命令后,在一定的时间范围内,对vscode中的代码进行保存后,会自动编译运行,保存几次后就报错,需要重新运行npmrundev,很耗费时间)后报错报错:CALL_AND_RETRY_LASTAllocationfailed-JavaScriptheapoutofmemory(CALL_AND_RETRY_LAS......
  • 【gopher的java学习笔记】Spring Boot Starter初探
    转到java这边后,这天需要搭一个java的webservice出来,如果是以前golang的话,那我就可以非常熟练的用gin搭建一个webservice出来,核心逻辑就是写好一些rest接口实现后再加上最为灵魂的一句://启动Gin服务器在8080端口router.Run(":8080")那来到java这边,我第一反应......
  • 科普文:Java基础系列【一文搞懂字节、位运算、及其应用】
    概叙字节(Byte)是计算机信息技术用于计量存储容量的一种计量单位‌。通常情况下,一字节等于八位(bit),即1Byte=8bit。(思考一下:为啥这么规定,单位是字节,且是8比特?)字节是计算机技术中最小的可操作存储单位,通常用于描述存储容量和传输容量。‌字节是通过网络传输信息或在硬盘或内......
  • 创建用于预测序列的人工智能模型,用Keras Tuner探索模型的超参数。
    上一篇:《创建用于预测序列的人工智能模型(五),调整模型的超参数》序言:在完成初步的模型研发后,接下来的重点是探索和优化超参数。通过合理调整超参数(如学习率、动量参数、神经元数量等),可以进一步提高模型的性能和准确性。这一过程需要结合工具(如KerasTuner)进行自动化测试和优化,从......
  • 【计算机毕业设计选题】最新毕设选题----基于Java的游戏推荐系统的设计与实现(源码+数
    博主介绍:原计算机互联网大厂开发,十年开发经验,带领技术团队几十名,专注技术开发,计算机毕设实战导师,专注Java、Python、小程序、安卓、深度学习和算法开发研究。主要服务内容:选题定题、开题报告、任务书、程序开发、文档编写和辅导、文档降重、程序讲解、答辩辅导等,欢迎咨询~......