JAVA 集合框架(四) Map集合详解和常用方法

Map集合是Java集合框架中的一个重要组成部分,它以键值对(key-value pairs)的形式存储数据。Map集合中的每个键都是唯一的,因此它不允许键的重复,而每个键可以关联一个值,同一键可以对应不同的值(在不改变键的情况下更新值)。Map 接口主要用于通过键快速查找、插入和删除对应的值。

Map接口的主要特征

  • 键-值存储:Map集合中每个元素都是一个键值对(KeyValuePair),通常写作<K, V>,其中K代表键的类型,V代表值的类型。
  • 唯一键约束:Map集合的键必须唯一,也就是说,如果试图插入一个与现有键相同的键,原有的键值对将被新的键值对替换(如果值不同的话)。
  • 键的无序性:Map集合中的元素不保证顺序,除非使用了如LinkedHashMap这样的有序Map实现类。
  • 常用操作:Map集合提供了丰富的API来添加、删除、查找、更新键值对,如put(key, value)(添加或更新键值对)、get(key)(通过键获取值)、remove(key)(通过键删除键值对)、containsKey(key)(检查Map中是否存在指定键)等。

Map接口的主要实现类

  • HashMap
    • 基于哈希表的实现,它允许空键和空值。
    • 迭代顺序不是基于插入顺序的。
  • LinkedHashMap
    • HashMap 的子类,维护了一个双向链表,可以按照插入顺序或访问顺序来遍历键值对。
  • TreeMap
    • 基于红黑树的实现,可以按照自然顺序或自定义顺序对键进行排序。
  • Hashtable
    • HashMap 类似,但它是线程安全的,不允许空键和空值。
  • ConcurrentHashMap
    • 线程安全的 HashMap 实现,用于多线程环境。
  • IdentityHashMap
    • 使用 == 而不是 equals() 方法来比较键。

Map接口的主要方法

添加键值对

  • V put(K key, V value):向Map中添加键值对,如果键已存在,则旧值将被新值替换并返回旧值;如果键不存在,则添加新的键值对并返回null。
// 创建一个 Map 集合
Map<String, Integer> myMap = new HashMap<>();
// 添加键值对
myMap.put("Apple", 1);
myMap.put("Banana", 2);
System.out.println(myMap); // 输出: {Apple=1, Banana=2}

获取值

  • V get(Object key):根据给定的键获取对应的值,如果键不存在,则返回null。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 获取值
Integer banana = myMap.get("Banana");
System.out.println(banana); // 输出: 2

删除键值对

  • V remove(Object key):删除指定键的键值对,如果键存在,则返回对应的值,否则返回null。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 删除键为"Apple"的键值对,并返回1
Integer removedValue  = myMap.remove("Apple");
System.out.println(removedValue);// 输出: 1
System.out.println(myMap);// 输出: {Pear=5, Mango=3, Orange=4, Banana=2}

判断键是否存在

  • boolean containsKey(Object key):判断Map中是否包含指定的键。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 判断 "Apple" 是否存在
boolean hasApple = myMap.containsKey("Apple");
System.out.println("键 Apple 是否存在: " + hasApple);// 输出: 键 Apple 是否存在: true

判断值是否存在

  • boolean containsValue(Object value):判断Map中是否包含指定的值。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 判断Value值 1 是否存在
boolean containsValue = myMap.containsValue(1);
System.out.println("值 1 是否存在? " + containsValue);// 输出: 值 1 是否存在? true

获取Map大小

  • int size():返回Map中键值对的数量。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 获取集合的大小
int mapSize = myMap.size();
System.out.println(mapSize);// 输出: 5

清空Map

  • void clear():删除Map中的所有键值对。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 清空Map
myMap.clear();
System.out.println(myMap);//输出: {}

获取所有键的集合

  • Set<K> keySet():返回一个包含所有键的Set集合。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 获得所有键的集合
Set<String> keys = myMap.keySet();
System.out.println(keys);//输出: [Apple, Pear, Mango, Orange, Banana]

获取所有值的集合

  • Collection<V> values():返回一个包含所有值的Collection集合。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 获取所有值的集合
Collection<Integer> values = myMap.values();
System.out.println(values);// 输出: [1, 5, 3, 4, 2]

获取键值对集合

  • Set<Map.Entry<K, V>> entrySet():返回一个包含所有键值对的Set集合,每个元素都是Map.Entry类型的对象。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<String, Integer> myMap =new HashMap<String, Integer>() {{put("Apple", 1);put("Banana", 2);put("Mango", 3);put("Orange", 4);put("Pear", 5);
}};
// 获取键值对
Set<Map.Entry<String, Integer>> entries = myMap.entrySet();
System.out.println(entries);// 输出: [Apple=1, Pear=5, Mango=3, Orange=4, Banana=2]

Map集合遍历

使用 keySet() 遍历键值对

  • keySet()方法返回一个包含所有键的Set视图,通过迭代这个Set可以获取到所有的键,再通过Map的get()方法取得对应的值。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<Integer, String> myMap =new HashMap<Integer, String>() {{put(1, "Apple");put(2, "Banana");put(3, "Mango");put(4, "Orange");put(5, "Pear");
}};
// 使用keySet遍历
for (Integer key : myMap.keySet()) {String value = myMap.get(key);System.out.println("Key: " + key + ", Value: " + value);
}

使用 entrySet() 遍历键值对

  • entrySet()方法返回一个包含所有键值对(Map.Entry对象)的Set视图,可以直接通过Map.Entry对象获取键和值。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<Integer, String> myMap =new HashMap<Integer, String>() {{put(1, "Apple");put(2, "Banana");put(3, "Mango");put(4, "Orange");put(5, "Pear");
}};
// 使用 entrySet() 遍历键值对
for (Map.Entry<Integer, String> entry : myMap.entrySet()) {// 获取 键Integer key = entry.getKey();// 获取 值String value = entry.getValue();System.out.println("Key: " + key + ", Value: " + value);
}

使用 forEach()

  • forEach()方法和Stream API是在Java 8中引入的,提供了更加简洁的遍历方式,尤其在处理集合时可以轻松实现链式操作。
// 创建一个 Map 集合,并在构造函数中直接添加初始键值对
Map<Integer, String> myMap =new HashMap<Integer, String>() {{put(1, "Apple");put(2, "Banana");put(3, "Mango");put(4, "Orange");put(5, "Pear");
}};
//  使用 forEach() 遍历输出
myMap.forEach((key,value)->System.out.println("Key: " + key + ", Value: " + value));

HashMap 集合

HashMap是基于哈希表实现的Map接口的一个非同步实现类,允许存储键值对(key-value pairs),并且可以高效地根据键来查找值。

  • 数据结构HashMap内部采用数组和链表(或红黑树,自JDK1.8开始)相结合的方式来存储数据。数组用于快速定位,链表或红黑树用于解决哈希冲突。
  • 键的唯一性:依赖hashCode方法和equals方法保证键的唯一
  • 初始化:如果键要存储的是自定义对象,需要重写hashCodeequals方法

代码示例

创建一个学生类,键是学生对象(Student):

import java.util.Objects;public class Student {private String mame;// 姓名private int age;// 年龄public Student() {}public Student(String mame, int age) {this.mame = mame;this.age = age;}public String getMame() {return mame;}public void setMame(String mame) {this.mame = mame;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}// 为了保证对象的唯一性,重写equals 和 hashCode// 如果学生对象的成员变量值相同,我们就认为是同一个对象@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(mame, student.mame);}@Overridepublic int hashCode() {return Objects.hash(mame, age);}
}

测试类:

//创建HashMap集合对象
HashMap<Student, String> stu = new HashMap<>();
// 创建学生对象
Student s1 = new Student("李一", 30);
Student s2 = new Student("李一", 30);
Student s3 = new Student("张三", 37);
Student s4 = new Student("李四", 32);// 把学生添加到集合
stu.put(s1,"北京");
stu.put(s2,"重庆");
stu.put(s3,"上海");
stu.put(s4,"曼哈顿");
// 遍历集合
for (Student key : stu.keySet()) {String value = stu.get(key);System.out.println(key.getName() + "," + key.getAge() + "," + value);
}

TreeMap集合

TreeMap是Java集合框架中实现Map接口的一个类,它使用红黑树(Red-Black Tree)作为底层数据结构,确保键的有序存储。

  • TreeMap的键值对是有序的,可以按照键的自然顺序(键实现Comparable接口)或者通过自定义Comparator进行排序。
  • 红黑树是一种自平衡二叉查找树,保证了插入、删除和查找操作的时间复杂度在最坏情况下均为O(log n)。

代码示例

创建一个学生类:

import java.util.Objects;public class Student implements Comparable<Student> {private String name;// 姓名private int age;// 年龄public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}// 为了保证对象的唯一性,重写equals 和 hashCode// 如果学生对象的成员变量值相同,我们就认为是同一个对象@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}// 继承 Comparable接口,重写 compareTo方法,实现学生根据条件进行排序@Overridepublic int compareTo(Student o) {//按照年龄进行排序int result = o.getAge() - this.getAge();//次要条件,按照姓名排序。result = result == 0 ? o.getName().compareTo(this.getName()) : result;return result;}
}

测试方法:

//创建TreeMap集合对象
TreeMap<Student, String> stu = new TreeMap<>();
// 创建学生对象
Student s1 = new Student("李一", 30);
Student s2 = new Student("李一", 30);
Student s3 = new Student("张三", 37);
Student s4 = new Student("李四", 32);// 把学生添加到集合
stu.put(s1,"北京");
stu.put(s2,"重庆");
stu.put(s3,"上海");
stu.put(s4,"曼哈顿");
// 遍历集合
for (Student key : stu.keySet()) {String value = stu.get(key);System.out.println(key.getName() + "," + key.getAge() + "," + value);
}

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

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

相关文章

CV method:最新Backbone---TransNeXt

文章目录 前言一、提出问题二、模型结构1. Pixel-focused Attention&#xff08;像素聚焦注意力机制&#xff09;2. Aggregating Diverse Attentions in a Single Mixer Query embedding3. ConvGLU4. 整体模型架构 三、方法论1. PFA设计原理2. Aggregating Diverse Attention原…

前端从零到一搭建脚手架并发布到npm

这里写自定义目录标题 一、为什么需要脚手架&#xff1f;二、前置-第三方工具的使用1. 创建demo并运行-4步新建文件夹 zyfcli&#xff0c;并初始化npm init -y配置入口文件 2.commander-命令行指令3. chalk-命令行美化工具4. inquirer-命令行交互工具5. figlet-艺术字6. ora-lo…

【算法】合并两个有序链表

本题来源---《合并两个有序链表》 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] /*** Definition for singl…

C++ - STL详解—vector类

一. vector的概念 向量&#xff08;Vector&#xff09;是一个封装了动态大小数组的顺序容器&#xff08;Sequence Container&#xff09;。跟任意其它类型容器一样&#xff0c;它能够存放各种类型的对象。可以简单的认为&#xff0c;向量是一个能够存放任意类型的动态数组。 …

win/mac达芬奇19下载:DaVinci Resolve Studio 19

DaVinci Resolve Studio 19 是一款功能强大的视频编辑和调色软件&#xff0c;广泛应用于电影、电视和网络节目的后期制作。这款软件不仅提供了专业的剪辑、调色和音频处理工具&#xff0c;还引入了全新的DaVinci Neural Engine AI工具&#xff0c;对100多项功能进行了大规模升级…

Vue3(五):组件通信详解(九种方法)

主要有九种方法&#xff0c;以下是详细解释及使用方法&#xff1a; 1.props props实现父子间的通信&#xff0c;是使用频率最高的。 &#xff08;1&#xff09;父传子&#xff1a;属性值是非函数。 以Father.vue和Child.vue 为例。 父组件中&#xff0c;引入子组件并给子组…

34、链表-合并K个升序链表

思路 1、直接全部放入集合中&#xff0c;然后排序&#xff0c;在进行构造节点返回 2、使用归并排序的方式&#xff0c;两两排序合并&#xff0c;最后合并大的。 3、第三中思路就比较巧妙了&#xff0c;可以使用小根堆&#xff0c;每次弹出堆顶&#xff0c;最小值&#xff0c…

【计算机网络】http协议的原理与应用,https是如何保证安全传输的

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

基于 RT-Thread 的 CMUX 串口多路复用的详细使用

一、CMUX 软件包的介绍 CMUX&#xff08;Connection Multiplexing &#xff09;&#xff0c;即连接&#xff08;串口&#xff09;多路复用&#xff0c;其功能主要在一个真实的物理通道上虚拟多个通道&#xff0c;每个虚拟通道上的连接和数据通讯可独立进行。  CMUX 软件包常用…

DRF ModelSerializer序列化类

ModelSerializer序列化类 【0】准备 模型表创建 from django.db import modelsclass Book(models.Model):name models.CharField(max_length64, verbose_name书名)price models.DecimalField(max_digits6, decimal_places2, verbose_name价格)publish models.ForeignKey(…

【C++打怪之路】-- C++开篇

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &…

vue-cli2 与vue-cli3,vue2与vue3 初始化项目,本地vue项目,详细解析区别(2024-04-19)

目录 1、区别&#xff08;vue-cli2 与 vue-cli3 &#xff09; 2、例子1&#xff08;vue2项目&#xff09; 2.1 版本与命令行 2.2 项目本地截图 2.3 项目文件解析 &#xff08;1&#xff09;package.json 文件 &#xff08;2&#xff09;webpack.dev.conf.js文件 &#…

[大模型]Qwen-7B-hat Transformers 部署调用

Qwen-7B-hat Transformers 部署调用 环境准备 在autodl平台中租一个3090等24G显存的显卡机器&#xff0c;如下图所示镜像选择PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打开刚刚租用服务器的JupyterLab&#xff0c;并且打开其中的终端开始环境配置、模型下…

NLP自然语言处理_序章

开一个新篇章&#xff0c;立一个flag&#xff0c;用一段时间来学习一下NLP&#xff0c;涨涨见识。 准备以B站 机器学习算法到transformer神经网络模型应用视频作为入门&#xff0c;此分类专门用于记录学习过程中的知识点以备自用。 一、何为NLP自然语言处理&#xff1f; NLP…

查看linux的主机配置脚本

废话不说 直接上指令 curl -Lso- bench.sh | bash 等待后&#xff0c;结果如图&#xff1a; 使用后没有问题&#xff0c;看情况使用 出事概不负责 介意勿用&#xff01;&#xff01;&#xff01;

RabbitMQ 各种通信模式的Python实现

一、RabbitMQ 原理 1、基本原理 RabbitMQ是流行的开源消息队列系统&#xff0c;用erlang语言开发。RabbitMQ是AMQP&#xff08;高级消息队列协议&#xff09;的标准实现。支持多种客户端&#xff0c;如&#xff1a;Python、Java、Javascript、C#、C/C,Go等&#xff0c;支持AJ…

使用yolov8 进行实例分割训练

1、基于windows 的ISAM标注 直接下载安装包&#xff0c;解压后即可使用 链接&#xff1a;https://pan.baidu.com/s/1u_6jk-7sj4CUK1DC0fDEXQ 提取码&#xff1a;c780 2、标注结果转yolo格式 通过ISAM标注后的json文件路径 原始json格式如下&#xff1a; ISAM.json 转 yolo.…

Leetcode算法训练日记 | day30

一、重新安排行程 1.题目 Leetcode&#xff1a;第 332 题 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发…

深入刨析 mysql 底层索引结构B+树

文章目录 前言一、什么是索引&#xff1f;二、不同索引结构对比2.1 二叉树2.2 平衡二叉树2.3 B-树2.4 B树 三、mysql 的索引3.1 聚簇索引3.2 非聚簇索引 前言 很多人看过mysql索引的介绍&#xff1a;hash表、B-树、B树、聚簇索引、主键索引、唯一索引、辅助索引、二级索引、联…

【Hadoop大数据技术】——Sqoop数据迁移(学习笔记)

&#x1f4d6; 前言&#xff1a;在实际开发中&#xff0c;有时候需要将HDFS或Hive上的数据导出到传统关系型数据库中&#xff08;如MySQL、Oracle等&#xff09;&#xff0c;或者将传统关系型数据库中的数据导入到HDFS或Hive上&#xff0c;如果通过人工手动进行数据迁移的话&am…