Java 中的 Map 集合及其子类详解:HashMap 和 TreeMap

news2024/11/4 17:17:47

Java 中的 Map 集合及其子类详解:HashMap 和 TreeMap

在 Java 编程中,Map 是一种用于存储键值对的集合结构。Java 提供了多种 Map 实现类,其中最常用的是 HashMapTreeMap


双列集合

在Java中,双列集合(也称为映射集合或字典)主要由Map接口及其实现类(如HashMapTreeMap)构成。双列集合的特点是通过键(Key)来唯一标识对应的值(Value),形成键值对的关系。

1. 定义和特性

双列集合的核心特性如下:

  • 键唯一性:每个键在集合中都是唯一的,不能重复。
  • 值可以重复:不同的键可以对应相同的值。
  • 高效查找:通过键查找值的时间复杂度通常为O(1)(在HashMap中)。

2. 主要实现类

  • HashMap:基于哈希表实现的Map接口,允许null键和null值,查找速度快,适合大多数情况。
  • TreeMap:基于红黑树实现的Map接口,按键的自然顺序或指定的比较器排序,不允许null键,查找速度较慢但有序。

3. 基本操作

以下是Map接口的一些常用方法:

方法名称说明
V put(K key, V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,即中键值对的个数

4. 应用场景

双列集合广泛应用于需要快速查找和存储关系的数据场景,例如:

  • 统计词频:使用单词作为键,出现次数作为值。
  • 缓存系统:存储数据和其对应的过期时间。
  • 配置参数:键为配置名,值为配置的具体内容。

1. Map 集合概述

1.1 Map 的基本概念

Map 是一个接口,表示存储键值对的数据结构。键的唯一性保证了查找、插入、删除的效率,值可以重复。常见的实现类有 HashMapTreeMap

interface Map<K,V>  // K: 键类型, V: 值类型

1.2 Map接口的特性

  • 键值对存储:每个元素由一个键和一个值组成,键用于索引,值是与键相关的数据。
  • 键唯一性Map中每个键都是唯一的,不能有重复键。如果使用相同的键插入新值,则原有值将被替换。
  • 无序性Map的元素通常是无序的,尤其是HashMapLinkedHashMap。某些实现(如TreeMap)会根据键的自然顺序或指定的比较器进行排序。
  • 允许空值:大多数Map实现允许一个null键和多个null值。

1.3 Map集合的三种遍历方式

在Java中,Map集合的遍历可以通过多种方式进行,每种方式都有其特点和适用场景。以下是对Map集合的三种主要遍历方式的详细介绍。

1. 使用 keySet() 方法遍历

keySet() 方法返回一个包含所有键的集合,我们可以通过这个集合来遍历 Map 中的每一个键,并根据键获取相应的值。

示例代码:
import java.util.HashMap;
import java.util.Map;

public class KeySetTraversal {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Orange", 3);

        // 使用 keySet() 遍历
        for (String key : map.keySet()) {
            Integer value = map.get(key);
            System.out.println("Key: " + key + ", Value: " + value);
        }
    }
}
2. 使用 entrySet() 方法遍历

entrySet() 方法返回一个包含所有键值对的集合,可以通过 Map.Entry 接口来同时获取键和值。这种方式更加高效,因为可以避免通过 get() 方法访问值。

示例代码:
import java.util.HashMap;
import java.util.Map;

public class EntrySetTraversal {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Orange", 3);

        // 使用 entrySet() 遍历
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println("Key: " + key + ", Value: " + value);
        }
    }
}
3. 使用 Java 8 的 forEach 方法

Java 8引入的 forEach 方法可以用来遍历 Map,这是一个非常方便和简洁的方式,尤其适合于流式编程。

示例代码:
import java.util.HashMap;
import java.util.Map;

public class ForEachTraversal {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Orange", 3);

        // 使用 forEach() 遍历
        map.forEach((key, value) -> {
            System.out.println("Key: " + key + ", Value: " + value);
        });
    }
}

2. HashMap

2.1 概述

HashMapMap接口的一个重要实现类,基于哈希表(Hash Table)实现。它提供了快速的查找、插入和删除操作,是在单线程环境中使用的理想选择。

2.2 特性

  • 存储结构:使用数组和链表(或红黑树)相结合来存储键值对。
  • 时间复杂度:在平均情况下,HashMap的插入、删除和查找操作的时间复杂度为O(1)。
  • 不保证顺序HashMap不保证元素的顺序,因此在遍历时,返回的顺序可能与插入顺序不同。
  • 允许null键和null值HashMap可以有一个null键和多个null值。

2.3 线程安全

HashMap 不是线程安全的,多个线程并发访问时可能导致数据不一致。可以使用 Collections.synchronizedMap() 方法来创建一个线程安全的 HashMap,或者使用 ConcurrentHashMap 来替代它。

2.4 使用场景

适合于频繁插入、删除操作且对元素顺序没有要求的场景。常见的使用场景包括缓存、数据库结果集的处理等。

2.5 性能

在适当的负载因子下,HashMap 的性能非常优秀,但在高并发情况下可能会出现性能下降的问题,因为它在扩容时会影响所有线程的性能。

2.6 底层原理

  1. HashMap底层是哈希表结构的
  2. 依赖nashCode方法和equals方法保证键的唯一
  3. 如果键存储的是自定义对象,需要重写hashCode:和equals方法,如果值存储自定义对象,不需要重写hashCode和equals方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.6 示例代码

import java.util.HashMap;

public class HashMapExample {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("苹果", 10);
        map.put("香蕉", 20);
        map.put("橘子", 30);

        System.out.println("香蕉的数量: " + map.get("香蕉"));
        map.remove("苹果");
        System.out.println("水果数量: " + map.size());
    }
}
注意事项
  • 并发问题HashMap在多线程环境中不安全,如果多个线程同时访问一个HashMap并至少一个线程在结构上进行修改,必须使用ConcurrentHashMap替代。
  • 负载因子:可以在创建HashMap时指定初始容量和负载因子,以优化性能。例如,HashMap<String, Integer> map = new HashMap<>(16, 0.75f);

3. LinkedHashMap

3.1 概述

LinkedHashMapHashMap的子类,具有HashMap的特性,同时维护元素的插入顺序。它在插入时使用双向链表来保持顺序。

3.2 特性

  • 存储结构:使用哈希表和双向链表来存储键值对。
  • 时间复杂度:与HashMap相同,插入、删除和查找的平均时间复杂度为O(1)。
  • 保持插入顺序:遍历LinkedHashMap时,返回的顺序是根据元素的插入顺序。
  • 允许null键和null值:与HashMap相同,可以有一个null键和多个null值。

3.3 线程安全

LinkedHashMap 也不是线程安全的,可以使用 Collections.synchronizedMap()ConcurrentHashMap 来确保线程安全。

3.4 使用场景

适合需要保持插入顺序的场景,如实现最近最少使用(LRU)缓存、保持插入顺序的结果集等。

3.5 示例代码

import java.util.LinkedHashMap;

public class LinkedHashMapExample {
    public static void main(String[] args) {
        LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
        map.put("苹果", 10);
        map.put("香蕉", 20);
        map.put("橘子", 30);

        for (String key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}

4. TreeMap

4.1 概述

TreeMap是基于红黑树实现的Map接口的一个实现类,提供了有序的键值对存储。

4.2 特性

  • 存储结构:使用红黑树存储键值对,保证键的有序性。
  • 时间复杂度:插入、删除和查找的时间复杂度为O(log n)。
  • 自然顺序或自定义顺序:可以根据键的自然顺序(Comparable)或指定的比较器(Comparator)进行排序。
  • 不允许null键TreeMap不允许null键,但允许多个null值。

4.3 线程安全

TreeMap 也不是线程安全的,建议在多线程环境中使用 ConcurrentSkipListMap 或通过 Collections.synchronizedMap() 来实现线程安全。

4.4 使用场景

适合需要按键排序的场景,如实现有序字典、范围查找等。

4.5 示例代码

import java.util.TreeMap;

public class TreeMapExample {
    public static void main(String[] args) {
        TreeMap<String, Integer> map = new TreeMap<>();
        map.put("苹果", 10);
        map.put("香蕉", 20);
        map.put("橘子", 30);

        for (String key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}

5. 线程安全问题的综合比较

特性HashMapLinkedHashMapTreeMap
线程安全
插入顺序无序有序有序
查找复杂度O(1)O(1)O(log n)
可存储空值否(键不能为null)

6. 选择合适的Map实现类

选择适当的 Map 实现类,取决于具体需求:

  • 若需要快速的查找性能且不关心元素顺序,选择 HashMap
  • 若需要保持元素插入顺序,选择 LinkedHashMap
  • 若需要按键的自然顺序或自定义顺序访问元素,选择 TreeMap

在多线程环境下,考虑使用 ConcurrentHashMapConcurrentSkipListMap,或者在每个 Map 访问上加锁,以确保线程安全。

7. 总结

在Java中,Map接口提供了强大的功能用于存储和操作键值对数据。HashMapLinkedHashMapTreeMap各自具有不同的特性和适用场景:

  • HashMap:快速存取,无序,适合性能要求高的场景。
  • LinkedHashMap:保持插入顺序,适合需要顺序访问的场景。
  • TreeMap:有序存储,适合需要排序和范围查询的场景。
    访问元素,选择 TreeMap

在多线程环境下,考虑使用 ConcurrentHashMapConcurrentSkipListMap,或者在每个 Map 访问上加锁,以确保线程安全。

7. 总结

在Java中,Map接口提供了强大的功能用于存储和操作键值对数据。HashMapLinkedHashMapTreeMap各自具有不同的特性和适用场景:

  • HashMap:快速存取,无序,适合性能要求高的场景。
  • LinkedHashMap:保持插入顺序,适合需要顺序访问的场景。
  • TreeMap:有序存储,适合需要排序和范围查询的场景。

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

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

相关文章

CoCode助力志晟信息成功通过CMMI五级复评!

热烈祝贺河北志晟信息技术股份有限公司在近期CMMI&#xff08;能力成熟度模型集成&#xff09;评估中&#xff0c;再次以卓越表现顺利通过CMMI成熟度五级的复评。 CoCode助力志晟信息通过CMMI五级 2024年9月1日至10日&#xff0c;CMMI评估组对志晟信息管理体系及其应用运行情况…

AD 授予委派full control权限后,部分用户无法unlock

文章目录 问题描叙根因解決方法&#xff1a; 问题描叙 通過委派方式授予被委派用戶full control 权限后&#xff0c;部分用户unlock是灰色显示&#xff1a; 根因 对比能正常unlock与无法unlock的用户&#xff0c;发现繼承無法unlock的用戶沒有"enable inheritance&quo…

css实现边框双色凹凸半圆

整体效果如下图&#xff1a; 结构代码&#xff1a; <div classline-outside-wrap><div classwrap><img src../img/avatar2x.png/><div classcontent-wrap></div></div></div> 内凹框实现&#xff1a; .content-wrap{width:100%;he…

算法深度剖析:前缀和

文章目录 前言一、一维前缀和模板二、二维前缀和模板三、寻找数组的中心下标四、除自身以外数组的乘积五、和为 K 的子数组六、和可被 K 整除的子数组七、连续数组八、矩阵区域和 前言 本章将深度剖析前缀和&#xff0c;以及总结前缀和模板。 前缀和是一种在算法和数据处理中…

关于我、重生到500年前凭借C语言改变世界科技vlog.14——常见C语言算法

文章目录 1.冒泡排序2.二分查找3.转移表希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 根据当前所学C语言知识&#xff0c;对前面知识进行及时的总结巩固&#xff0c;出了这么一篇 vlog 介绍当前所学知识能遇到的常见算法&#xff0c;这些算法是…

特定领域的Embeddings模型微调全面指南

假设你正在为医学领域构建一个问答系统。你希望确保当用户提出问题时&#xff0c;系统能够准确地检索相关的医学文章。但是通用的嵌入模型可能在处理医学术语的高度专业化词汇和细微差别时会遇到困难。 这时候&#xff0c;微调就能派上用场了&#xff01;&#xff01;&#xf…

视频推荐的算法(字节青训)

题目&#xff1a; 西瓜视频 正在开发一个新功能&#xff0c;旨在将访问量达到80百分位数以上的视频展示在首页的推荐列表中。实现一个程序&#xff0c;计算给定数据中的80百分位数。 例如&#xff1a;假设有一个包含从1到100的整数数组&#xff0c;80百分位数的值为80&#…

安卓13默认连接wifi热点 android13默认连接wifi

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 有时候我们需要让固件里面内置好,相关的wifi的ssid和密码,让固件起来就可以连接wifi,不用在手动操作。 2.问题分析 这个功能,使用普通的安卓代码就可以实现了。 3.代…

详解RabbitMQ三种队列类型

RabbitMQ 是一个强大的消息队列系统&#xff0c;它提供了多种队列类型以满足不同的使用需求。本文将探讨三种主要队列类型&#xff1a;经典队列、仲裁队列和流式队列&#xff0c;并讨论它们的区别和选型建议。 经典队列&#xff08;Classic Queues&#xff09; 简介&#xff…

CytoSPACE·空转和单细胞数据的高分辨率比对

1. 准备输入文件&#xff0c;需要四个文件&#xff0c;所有文件都应以制表符分隔的表格输入格式 (.txt) 提供。 a. scRNA-seq 基因表达文件 矩阵必须是基因&#xff08;行&#xff09;乘以细胞&#xff08;列&#xff09;。 第一行必须包含单个细胞 ID&#xff0c;第一列必须…

react使用Fullcalendar

前言&#xff1a; 最近在做项目时&#xff0c;遇到了需要用日历的项目。一开始考虑使用antd的日历组件。后来 调研技术库&#xff0c;发现了fullcalendar 库。经过对比 fullcalendar 更强大&#xff0c;更灵活。 其实 antd的日历组件 也不错&#xff0c;简单的需求用他也行。…

LabVIEW过程控制实验平台

A3000实验平台通过LabVIEW开发&#xff0c;实现了过程控制的虚拟仿真与实时通信&#xff0c;显著提高了教学与实验的互动性和效率。该平台采用模块化设计&#xff0c;支持多种控制策略的实验教学&#xff0c;克服了传统实验设备的不足。项目背景 目前高校过程控制实验设备普遍…

腾讯会议pc端3.29.11开启悬浮窗口

之前是&#xff1a;pc端每次最小化&#xff0c;它就自动收回到任务栏里了 版本&#xff1a;3.29.11 解决办法&#xff1a; 打开腾讯会议&#xff0c;点击左上角的【头像】。 单击【设置】。 选择【显示当前说话者】来管理麦克风浮窗。 再进入会议&#xff0c;点击最小化一哈&…

聊一聊:ChatGPT搜索引擎会取代谷歌和百度吗?

当地时间 10 月 31 日&#xff0c;OpenAI 正式推出了 ChatGPT 搜索功能&#xff0c;能实时、快速获取附带相关网页来源链接的答案。这一重大升级标志着其正式向谷歌的搜索引擎霸主地位发起挑战。 本周五我们聊一聊&#xff1a; 欢迎在评论区畅所欲言&#xff0c;分享你的观点~ …

贪心算法习题其四【力扣】【算法学习day.21】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

python实战项目52:Selenium爬取steam黑神话悟空评论

python实战项目52:Selenium爬取steam黑神话悟空评论 一、思路分析二、完整代码一、思路分析 Selenium爬取steam游戏评论的思路非常简单,初始化Chromedriver,然后打开评论页面,循环下拉滚动条,每下拉一次滚动条获取一次页面源代码,使用xpath解析数据并保存数据。本文的主…

Claude 3.5 新功能 支持对 100 页的PDF 图像、图表和图形进行可视化分析

Claude 3.5 Sonnet发布PDF图像预览新功能&#xff0c;允许用户分析长度不超过100页的PDF中的视觉内容。 此功能使用户能够轻松上传文档并提取信息&#xff0c;特别适用于包含图表、图形和其他视觉元素的研究论文和技术文档。 视觉PDF分析&#xff1a;用户现在可以从包含各种视觉…

【Qt c++】Qt内置图标

Qt内置图标 前言简例示例 前言 Qt内置图标封装在QStyle中&#xff0c;大概七十多个图标&#xff0c;可以直接拿来用。图标的大小&#xff1a;我认为 size 30 还是可以的. 简例 SP_TitleBarMenuButton, SP_TitleBarMinButton, SP_TitleBarMaxButton, SP_TitleBarCloseButton…

Redis 的使⽤和原理

第一章:初识 Redis 1.1盛赞 Redis Redis 是⼀种基于键值对&#xff08;key-value&#xff09;的 NoSQL 数据库&#xff0c;与很多键值对数据库不同的是&#xff0c;Redis 中的值可以是由 string&#xff08;字符串&#xff09;、hash&#xff08;哈希&#xff09;、list&…

【Clikhouse 探秘】ClickHouse 物化视图:加速大数据分析的新利器

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…