当前位置: 首页 > news >正文

Java集合框架--Map

在Java中,"map" 是一个非常重要的接口,它属于 java.util 包。Map 是一种将键(key)映射到值(value)的对象,一个键可以最多映射到最多一个值。这意味着,Map 接口的实现(如 HashMap、TreeMap 等)提供了一种存储键值对(key-value pairs)的方式,其中每个键都是唯一的。

Map 方法:

Map 接口提供了多种方法用于插入、检索、删除键值对以及遍历 Map 中的元素。这里是一些常用的 Map 方法:

put(K key, V value)

  • put(K key, V value): 将指定的值与此映射中的指定键关联(可选操作)。
    Map<String, Integer> map = new HashMap<>();
    map.put("apple", 100); // 将键 "apple" 与值 100 关联

get(Object key)

  • get(Object key): 返回指定键所映射的值;如果此映射不包含该键的映射,则返回 null
Integer value = map.get("apple"); // 返回与键 "apple" 关联的值,即 100
if (value != null) {System.out.println("The value of 'apple' is: " + value);
} else {System.out.println("The key 'apple' does not exist in the map.");
}

remove(Object key)

  • remove(Object key): 如果存在(即以前或显式地)将指定键映射到此映射,则将其删除(可选操作)。
    map.remove("apple"); // 删除键 "apple" 及其对应的值
    if (!map.containsKey("apple")) {System.out.println("The key 'apple' has been removed from the map.");
    }

containsKey(Object key)

  • containsKey(Object key): 如果此映射包含指定键的映射,则返回 true
    if (map.containsKey("banana")) {System.out.println("The map contains the key 'banana'.");
    } else {System.out.println("The map does not contain the key 'banana'.");
    }

containsValue(Object value)

  • containsValue(Object value): 如果此映射将一个或多个键映射到指定值,则返回 true
    if (map.containsValue(100)) {System.out.println("The map contains the value 100.");
    } else {System.out.println("The map does not contain the value 100.");
    }

entrySet()

  • entrySet(): 返回包含此映射中所包含的映射的 Set 视图。
    for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
    }

keySet()

  • keySet(): 返回此映射中包含的键的 Set 视图。
    for (String key : map.keySet()) {System.out.println("Key = " + key);
    }

values()

  • values(): 返回此映射中包含的值的 Collection 视图。
    for (Integer value : map.values()) {System.out.println("Value = " + value);
    }

Map 接口的实现类:

Map 接口的实现类,如 HashMap 和 TreeMap,提供了不同的性能特性和排序保证。HashMap 提供了快速的键值查找能力,但不保证映射的顺序;而 TreeMap 则基于红黑树实现,可以保证键的自然顺序或创建映射时提供的 Comparator 进行排序。

 HashMap 

  1. 在Java中,HashMap 是 java.util 包下的一个非常重要的类,它实现了 Map 接口。HashMap 存储键值对(key-value pairs),其中每个键都是唯一的,并且映射到最多一个值。HashMap 允许使用 null 值和 null 键(但最多只能有一个 null 键)。
  2. HashMap 提供了快速的键值查找能力,因为它基于哈希表实现。不过,需要注意的是,HashMap 不保证映射的顺序;特别是,它不保证随着时间的推移顺序保持不变。

HashMap的主要特点包括:

  1. 基于哈希表实现:HashMap内部通过哈希表来存储键值对,这使得它能够提供快速的键值查找能力。
  2. 不保证映射顺序:HashMap不保证映射的顺序;特别是,它不保证随着时间的推移顺序保持不变。当你遍历HashMap时,元素的顺序可能会发生变化。
  3. 允许使用null键和null值:HashMap允许最多一个null键和多个null值。这意呀着你可以将null作为键或值存储在HashMap中,但请注意,由于键的唯一性,HashMap中只能有一个null键。
  4. 键的唯一性:HashMap中的每个键都是唯一的,这意味着两个不同的键不能映射到相同的值(尽管不同的键可以映射到相同的值,即值可以是重复的)。
  5. 性能高效:由于HashMap基于哈希表实现,并且具有较好的哈希函数和冲突解决策略(如链地址法),因此它在大多数情况下能够提供常数时间复杂度的查找、插入和删除操作(平均情况下)。然而,在最坏的情况下(如哈希冲突非常严重时),这些操作的时间复杂度可能会退化到O(n)。
  6. 线程不安全:HashMap不是线程安全的。如果在多线程环境中需要共享HashMap,那么需要额外的同步措施,或者使用ConcurrentHashMap等线程安全的替代方案。

这些特点使得HashMap成为在Java中存储键值对时的一个非常流行和有用的选择,特别是在不需要保持映射顺序的场景下。

HashMap 的一些常用方法:

  • put(K key, V value): 将指定的值与此映射中的指定键关联(可选操作)。
  • get(Object key): 返回指定键所映射的值;如果此映射不包含该键的映射,则返回 null
  • remove(Object key): 如果存在(即以前或显式地)将指定键映射到此映射,则将其删除(可选操作)。
  • containsKey(Object key): 如果此映射包含指定键的映射,则返回 true
  • containsValue(Object value): 如果此映射将一个或多个键映射到指定值,则返回 true

HashMap演示这些方法:

import java.util.HashMap;
import java.util.Map;public class HashMapExample {public static void main(String[] args) {// 创建一个HashMap实例Map<String, Integer> map = new HashMap<>();// 使用put方法添加键值对map.put("apple", 100);map.put("banana", 200);// 使用get方法获取键对应的值Integer value = map.get("apple");if (value != null) {System.out.println("The value of 'apple' is: " + value);} else {System.out.println("The key 'apple' does not exist in the map.");}// 使用remove方法删除键值对map.remove("banana");if (!map.containsKey("banana")) {System.out.println("The key 'banana' has been removed from the map.");}// 使用containsKey方法检查键是否存在if (map.containsKey("apple")) {System.out.println("The map contains the key 'apple'.");}// 使用containsValue方法检查值是否存在if (map.containsValue(100)) {System.out.println("The map contains the value 100.");}// 遍历HashMap// 使用keySet遍历键for (String key : map.keySet()) {System.out.println("Key: " + key);}// 使用values遍历值for (Integer val : map.values()) {System.out.println("Value: " + val);}// 使用entrySet遍历键值对for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());}}
}

在这个例子中,我们首先创建了一个HashMap实例,并使用put方法添加了两个键值对("apple" -> 100 和 "banana" -> 200)。然后,我们使用get方法获取了键"apple"对应的值,并打印出来。接着,我们使用remove方法删除了键"banana"及其对应的值,并检查它是否已被删除。我们还展示了如何使用containsKeycontainsValue方法来检查键和值是否存在。最后,我们通过遍历keySetvaluesentrySet来展示了如何遍历HashMap中的键、值和键值对。

使用HashMap实现处理学生信息

这个例子将涉及到HashMap的高级用法,包括遍历、条件查找、以及结合其他数据结构如List来解决问题。

假设我们有一个场景,我们需要管理一个学校的课程信息,包括课程的ID、名称、以及选修该课程的学生列表。为了高效地处理这些信息,我们可以使用HashMap来存储课程ID到课程信息的映射,其中课程信息是一个包含课程名称和学生列表的对象。

首先,我们定义一个简单的CourseInfo类来表示课程信息:

import java.util.ArrayList;
import java.util.List;public class CourseInfo {private String courseName;private List<String> students;public CourseInfo(String courseName) {this.courseName = courseName;this.students = new ArrayList<>();}public void addStudent(String studentName) {students.add(studentName);}public String getCourseName() {return courseName;}public List<String> getStudents() {return students;}@Overridepublic String toString() {return "CourseInfo{" +"courseName='" + courseName + '\'' +", students=" + students +'}';}
}

然后,我们使用HashMap来管理课程信息:

import java.util.HashMap;
import java.util.Map;public class SchoolCourses {private Map<String, CourseInfo> courses;public SchoolCourses() {this.courses = new HashMap<>();}public void addCourse(String courseId, String courseName) {if (!courses.containsKey(courseId)) {courses.put(courseId, new CourseInfo(courseName));}}public void addStudentToCourse(String courseId, String studentName) {if (courses.containsKey(courseId)) {courses.get(courseId).addStudent(studentName);} else {System.out.println("Course ID does not exist.");}}// 示例:遍历所有课程并打印信息public void printAllCourses() {for (Map.Entry<String, CourseInfo> entry : courses.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());}}// 示例:根据课程ID查找并打印课程信息public void printCourseInfo(String courseId) {if (courses.containsKey(courseId)) {System.out.println(courses.get(courseId));} else {System.out.println("Course ID does not exist.");}}public static void main(String[] args) {SchoolCourses schoolCourses = new SchoolCourses();schoolCourses.addCourse("CS101", "Introduction to Computer Science");schoolCourses.addStudentToCourse("CS101", "Alice");schoolCourses.addStudentToCourse("CS101", "Bob");schoolCourses.addCourse("MATH101", "Mathematics for Computer Science");schoolCourses.addStudentToCourse("MATH101", "Charlie");schoolCourses.printAllCourses();schoolCourses.printCourseInfo("CS101");}
}

在这个例子中,SchoolCourses类使用HashMap来管理课程信息。我们定义了addCourse方法来添加新课程,addStudentToCourse方法来为指定课程添加学生,以及printAllCoursesprintCourseInfo方法来遍历和打印课程信息。这个示例展示了如何在复杂场景中有效地使用HashMap来管理和检索数据。

小提示:

HashMap 的性能特性使其成为在不需要保持映射顺序的场景下存储键值对的理想选择。然而,如果你需要保持键的自然顺序或根据创建映射时提供的 Comparator 进行排序,那么 TreeMap 可能是更好的选择。

TreeMap

  • TreeMap是Java中的一个非常有用的数据结构,它实现了SortedMap接口,这意味着它不仅能够存储键值对,还能确保所有的键都处于排序状态。TreeMap基于红黑树实现,这保证了它具有良好的查找、插入和删除性能,时间复杂度通常为O(log n)。
  • 在TreeMap中,每个键都必须实现Comparable接口,或者你可以在创建TreeMap时提供一个Comparator来指定键的排序方式。如果没有提供Comparator,那么键的自然顺序将被用来排序。

TreeMap的主要特点:

  1. 它保证映射按照键的排序顺序进行视图迭代(包括分割器提供的弱视图)。
  2. 它不允许有重复的键;每个键最多只能映射到一个值。
  3. 它实现了NavigableMap接口,提供了比SortedMap更多的导航方法,如firstKey()lastKey()headMap(K toKey)等。

TreeMap非常适合于需要按键排序的映射场景,比如存储学生成绩、员工信息等,并且需要经常进行范围查询或排序操作。

TreeMap的常用方法:

  1. put(K key, V value): 将指定的值与此映射中的指定键关联(可选操作)。如果映射以前包含该键的映射,则旧值将被替换。

  2. get(Object key): 返回指定键所映射的值;如果此映射不包含该键的映射,则返回null

  3. remove(Object key): 如果存在(即以前或显式地)将指定键映射到此映射,则将其删除(可选操作)。

  4. containsKey(Object key): 如果此映射包含指定键的映射,则返回true

  5. containsValue(Object value): 如果此映射将一个或多个键映射到指定值,则返回true

  6. firstKey(): 返回此映射中当前第一个(最低)键。

  7. lastKey(): 返回此映射中当前最后一个(最高)键。

  8. headMap(K toKey): 返回此映射中部分视图,其键小于toKey(不包含toKey)。

  9. tailMap(K fromKey): 返回此映射中部分视图,其键大于或等于fromKey

  10. subMap(K fromKey, K toKey): 返回此映射中部分视图,其键的范围从fromKey(包含)到toKey(不包含)。

  11. entrySet(): 返回包含此映射中所包含的映射的Set视图。该集合的元素是Map.Entry对象,它们反映了映射的迭代顺序。

  12. keySet(): 返回此映射中包含的键的Set视图。该集合的元素按映射的排序顺序排列。

  13. values(): 返回此映射中包含的值的Collection视图。这个集合包含的元素是按映射的键排序顺序对应的值。

请注意,TreeMap的键是有序的,这是它与HashMap(无序)的主要区别之一。当你需要对键进行排序或频繁地进行范围查询时,TreeMap是非常有用的。

TreeMap中这些方法的基本使用:

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;public class TreeMapExample {public static void main(String[] args) {// 创建一个TreeMap实例TreeMap<Integer, String> treeMap = new TreeMap<>();// 使用put方法添加键值对treeMap.put(1, "One");treeMap.put(3, "Three");treeMap.put(2, "Two");// 使用get方法获取键对应的值System.out.println("The value for key 2 is: " + treeMap.get(2));// 使用remove方法删除键值对treeMap.remove(3);// 使用containsKey方法检查键是否存在System.out.println("Does the map contain key 1? " + treeMap.containsKey(1));// 使用containsValue方法检查值是否存在System.out.println("Does the map contain value 'Three'? " + treeMap.containsValue("Three")); // 这将返回false,因为'Three'已被删除// 使用firstKey和lastKey方法获取第一个和最后一个键System.out.println("First key: " + treeMap.firstKey());System.out.println("Last key: " + treeMap.lastKey());// 使用headMap获取小于某个键的所有键值对Map<Integer, String> head = treeMap.headMap(2);System.out.println("Head map (keys < 2): " + head);// 使用tailMap获取大于或等于某个键的所有键值对Map<Integer, String> tail = treeMap.tailMap(2);System.out.println("Tail map (keys >= 2): " + tail);// 使用subMap获取键在某个范围内的所有键值对Map<Integer, String> sub = treeMap.subMap(1, 3);System.out.println("Sub map (keys 1 to 2): " + sub);// 使用entrySet获取所有键值对的集合Set<Map.Entry<Integer, String>> entries = treeMap.entrySet();for (Map.Entry<Integer, String> entry : entries) {System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());}// 使用keySet获取所有键的集合Set<Integer> keys = treeMap.keySet();for (Integer key : keys) {System.out.println("Key: " + key);}// 使用values获取所有值的集合java.util.Collection<String> values = treeMap.values();for (String value : values) {System.out.println("Value: " + value);}}
}

在这个例子中,创建了一个TreeMap实例,并使用put方法添加了一些键值对。然后,展示了如何使用getremovecontainsKeycontainsValuefirstKeylastKeyheadMaptailMapsubMapentrySetkeySetvalues方法来操作这个映射。注意,由于TreeMap保持键的排序顺序,因此当你遍历键、值或键值对时,它们将按照排序顺序出现。

使用HashMap实现处理图书信息

在这个示例中,使用TreeMap来管理一个图书馆中书籍的借阅记录,其中书籍的ISBN作为键,借阅记录作为值。借阅记录将是一个简单的类,包含借阅者的姓名和借阅日期。

首先,我们定义借阅记录类BorrowRecord

import java.time.LocalDate;public class BorrowRecord {private String borrowerName;private LocalDate borrowDate;public BorrowRecord(String borrowerName, LocalDate borrowDate) {this.borrowerName = borrowerName;this.borrowDate = borrowDate;}public String getBorrowerName() {return borrowerName;}public LocalDate getBorrowDate() {return borrowDate;}@Overridepublic String toString() {return "BorrowRecord{" +"borrowerName='" + borrowerName + '\'' +", borrowDate=" + borrowDate +'}';}
}

然后,我们使用TreeMap来管理书籍的借阅记录:

import java.time.LocalDate;
import java.util.TreeMap;public class LibraryBorrowRecords {private TreeMap<String, BorrowRecord> borrowRecords;public LibraryBorrowRecords() {// 使用自然顺序(String的字典序)来排序ISBNthis.borrowRecords = new TreeMap<>();}// 添加借阅记录public void addBorrowRecord(String isbn, String borrowerName, LocalDate borrowDate) {borrowRecords.put(isbn, new BorrowRecord(borrowerName, borrowDate));}// 查找并返回指定ISBN的借阅记录public BorrowRecord getBorrowRecord(String isbn) {return borrowRecords.get(isbn);}// 遍历并打印所有借阅记录public void printAllBorrowRecords() {for (Map.Entry<String, BorrowRecord> entry : borrowRecords.entrySet()) {System.out.println("ISBN: " + entry.getKey() + ", " + entry.getValue());}}public static void main(String[] args) {LibraryBorrowRecords library = new LibraryBorrowRecords();// 添加一些借阅记录library.addBorrowRecord("978-1234567890", "Alice", LocalDate.of(2023, 10, 1));library.addBorrowRecord("978-0987654321", "Bob", LocalDate.of(2023, 10, 5));library.addBorrowRecord("978-1122334455", "Charlie", LocalDate.of(2023, 10, 10));// 打印所有借阅记录library.printAllBorrowRecords();// 查找并打印特定ISBN的借阅记录BorrowRecord record = library.getBorrowRecord("978-1234567890");if (record != null) {System.out.println("Borrow record for ISBN 978-1234567890: " + record);} else {System.out.println("No borrow record found for ISBN 978-1234567890.");}}
}

在这个示例中,我们创建了一个LibraryBorrowRecords类来管理借阅记录,其中使用了TreeMap来存储ISBN到借阅记录的映射。我们定义了添加借阅记录、查找借阅记录和打印所有借阅记录的方法。在main方法中,我们创建了一个LibraryBorrowRecords实例,添加了一些借阅记录,并展示了如何遍历和查找特定的借阅记录。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • MySQL 关系设计详解
  • <数据集>遥感船舶识别数据集<目标检测>
  • 嵌入式系统:全面解读与关键要点
  • Flink CDC Standalone模式部署及Flink CDC Job提交
  • 深入理解 Vue 3 的双向绑定原理与实现
  • ARM/Linux嵌入式面经(二六):韶音
  • 【记录】MICCAI BraTs 2020数据集
  • shell脚本中$0 $1 $# $@ $* $? $$ 的各种符号意义详解
  • 小阿轩yx-Kubernetes Pod调度基础
  • 服务路由(Service Routing)
  • Eagle 4.0:强大插件加持的素材收集管理工具
  • 大数据ETL工具(Sqoop, DataX, Kettle)对比
  • 带有限制编辑的PDF文件怎么取消编辑限制
  • 3ds Max - 导出顶点色模型
  • 计算机网络速成(三)
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • C++类的相互关联
  • canvas 绘制双线技巧
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • PHP那些事儿
  • Sass Day-01
  • session共享问题解决方案
  • spring boot 整合mybatis 无法输出sql的问题
  • tensorflow学习笔记3——MNIST应用篇
  • 对JS继承的一点思考
  • 分布式熔断降级平台aegis
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 普通函数和构造函数的区别
  • 驱动程序原理
  • 如何进阶一名有竞争力的程序员?
  • 入门级的git使用指北
  • 写给高年级小学生看的《Bash 指南》
  • 异常机制详解
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 在Mac OS X上安装 Ruby运行环境
  • Java性能优化之JVM GC(垃圾回收机制)
  • 带你开发类似Pokemon Go的AR游戏
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • #if 1...#endif
  • #控制台大学课堂点名问题_课堂随机点名
  • ( 10 )MySQL中的外键
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (Matlab)使用竞争神经网络实现数据聚类
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (备份) esp32 GPIO
  • (二)原生js案例之数码时钟计时
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (四)React组件、useState、组件样式
  • (转)3D模板阴影原理
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • . NET自动找可写目录
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料