news 2026/10/29 11:02:42

# Java Map 实战:从授课安排增删改到世界杯冠军双向查询

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
# Java Map 实战:从授课安排增删改到世界杯冠军双向查询
# Java Map 实战:从授课安排增删改到世界杯冠军双向查询 > 上一篇写了 Map 的基础 API 和三种遍历。这篇直接上三个真实小案例:老师授课安排的增删改查、按年份查世界杯冠军、按球队反查夺冠年份列表。重点不在写代码,而在体会「什么场景该用 Map」以及「双向查询时怎么设计 Map」。 ## 案例一:老师授课安排的增删改查 题目场景:用 Map 存「老师 → 所授课程」,要完成新增老师、修改老师课程、遍历输出、筛选教某门课的老师、统计某门课有几位老师。 ```java import java.util.HashMap; import java.util.Map; public class CourseSchedule { public static void main(String[] args) { // 键:老师姓名;值:教授的课程 Map<String, String> courseMap = new HashMap<>(); courseMap.put("张三", "Java"); courseMap.put("李四", "JSP"); courseMap.put("王五", "CoreJava"); courseMap.put("赵六", "JSP"); // (2) 新增一位老师 Allen 教 JDBC courseMap.put("Allen", "JDBC"); // (3) Lucy 改教 CoreJava —— put 同 key 即覆盖 courseMap.put("Lucy", "CoreJava"); // (4) 遍历输出所有老师及课程 System.out.println("===== 当前授课安排 ====="); for (Map.Entry<String, String> e : courseMap.entrySet()) { System.out.println(e.getKey() + " -> " + e.getValue()); } // (5) 输出所有教 JSP 的老师 System.out.println("\n===== 教 JSP 的老师 ====="); for (Map.Entry<String, String> e : courseMap.entrySet()) { if ("JSP".equals(e.getValue())) { System.out.println(e.getKey()); } } // (6) 统计教 CoreJava 和 JDBC 的老师人数 int coreJavaCount = 0, jdbcCount = 0; for (String course : courseMap.values()) { if ("CoreJava".equals(course)) coreJavaCount++; if ("JDBC".equals(course)) jdbcCount++; } System.out.println("\n教 CoreJava 的老师有 " + coreJavaCount + " 位"); System.out.println("教 JDBC 的老师有 " + jdbcCount + " 位"); } } ``` 运行结果: ``` ===== 当前授课安排 ===== 张三 -> Java 李四 -> JSP 王五 -> CoreJava 赵六 -> JSP Allen -> JDBC Lucy -> CoreJava ===== 教 JSP 的老师 ===== 李四 赵六 教 CoreJava 的老师有 2 位 教 JDBC 的老师有 1 位 ``` 这里要记住两个操作直觉: - **修改课程**不是什么复杂方法,就是 `map.put(老师名, 新课程)`——因为 key 唯一,同 key 再 put 就是覆盖; - **按课程反查老师/统计人数**,本质是遍历 `values()` 做条件过滤。value 不是键,所以无法直接 `get`,只能扫一遍。 ## 案例二:输入年份,查该年世界杯冠军 场景很常见:存一张「年份 → 冠军球队」的对照表,输入年份输出球队,没举办过就提示。 ```java import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class WorldCupQuery { public static void main(String[] args) { // 历年世界杯冠军(1930 年首届,1942/1946 因二战停办) Map<String, String> championMap = new HashMap<>(); championMap.put("1930", "乌拉圭"); championMap.put("1934", "意大利"); championMap.put("1938", "意大利"); championMap.put("1950", "乌拉圭"); championMap.put("1954", "西德"); championMap.put("1958", "巴西"); championMap.put("1962", "巴西"); championMap.put("1966", "英格兰"); championMap.put("1970", "巴西"); championMap.put("1974", "西德"); championMap.put("1978", "阿根廷"); championMap.put("1982", "意大利"); championMap.put("1986", "阿根廷"); championMap.put("1990", "西德"); championMap.put("1994", "巴西"); championMap.put("1998", "法国"); championMap.put("2002", "巴西"); championMap.put("2006", "意大利"); championMap.put("2010", "西班牙"); championMap.put("2014", "德国"); championMap.put("2018", "法国"); championMap.put("2022", "阿根廷"); Scanner sc = new Scanner(System.in); System.out.print("请输入年份:"); String year = sc.next(); String champion = championMap.get(year); if (champion == null) { System.out.println(year + " 年没有举办世界杯"); } else { System.out.println(year + " 年世界杯冠军是:" + champion); } sc.close(); } } ``` 测试: ``` 请输入年份:2002 2002 年世界杯冠军是:巴西 请输入年份:1942 1942 年没有举办世界杯 ``` 这是最典型的「查找表」用法:Map 就是一张查表字典,key 是要查的条件,value 是结果。 ## 案例三:输入球队名,反查所有夺冠年份 题目进阶:输入「巴西」要输出它夺冠的所有年份 `1958、1962、1970、1994、2002`;输入「荷兰」要输出「没有获得过世界杯」。 ### 思路一:遍历正向 Map(简单但慢) 直接拿上一个 `championMap`,遍历每个 entry,只要 value 等于输入球队就收集 key: ```java Map<String, Integer> result = new HashMap<>(); // 仅示意收集逻辑 java.util.List<String> years = new java.util.ArrayList<>(); for (Map.Entry<String, String> e : championMap.entrySet()) { if (e.getValue().equals("巴西")) { years.add(e.getKey()); } } ``` 数据量小的时候完全够用,但每次反查都要扫整张表。 ### 思路二:专门建一张反向 Map(推荐) 既然经常要「按球队查年份」,干脆预先维护一张 `球队 -> 年份列表` 的反向表,查询时直接 `get(球队名)`,O(1): ```java import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; public class WorldCupReverse { public static void main(String[] args) { // 正向表:年份 -> 球队 Map<String, String> yearToTeam = new HashMap<>(); yearToTeam.put("1958", "巴西"); yearToTeam.put("1962", "巴西"); yearToTeam.put("1970", "巴西"); yearToTeam.put("1994", "巴西"); yearToTeam.put("2002", "巴西"); yearToTeam.put("1930", "乌拉圭"); yearToTeam.put("1950", "乌拉圭"); yearToTeam.put("1978", "阿根廷"); yearToTeam.put("1986", "阿根廷"); yearToTeam.put("2022", "阿根廷"); yearToTeam.put("1998", "法国"); yearToTeam.put("2018", "法国"); yearToTeam.put("1966", "英格兰"); yearToTeam.put("2010", "西班牙"); // 构建反向表:球队 -> 该队夺冠年份列表 Map<String, List<String>> teamToYears = new HashMap<>(); for (Map.Entry<String, String> e : yearToTeam.entrySet()) { String team = e.getValue(); String year = e.getKey(); // computeIfAbsent:没有这个 key 就先放一个空 List,再往里加 teamToYears.computeIfAbsent(team, k -> new ArrayList<>()).add(year); } Scanner sc = new Scanner(System.in); System.out.print("请输入球队名:"); String team = sc.next(); List<String> years = teamToYears.get(team); if (years == null || years.isEmpty()) { System.out.println(team + " 没有获得过世界杯"); } else { System.out.print(team + " 夺冠年份:"); System.out.println(String.join("、", years)); } sc.close(); } } ``` 测试: ``` 请输入球队名:巴西 巴西 夺冠年份:1958、1962、1970、1994、2002 请输入球队名:荷兰 荷兰 没有获得过世界杯 ``` 这里有两个新东西值得记: - **反向 Map 的 value 用 `List`**:因为一支球队可以对应多个年份,一个 key 对应一个值不够,值本身得是个集合; - **`computeIfAbsent(key, k -> new ArrayList<>())`**:一行搞定「没有就建空列表,有就拿出来」,比传统的 `if (!containsKey) put` 简洁很多。 ## 四、什么时候用哪种 Map 实现? | 实现类 | 特点 | 适用场景 | |---|---|---| | `HashMap` | 无序、查询快、key 允许一个 null | 默认首选,大部分业务场景 | | `LinkedHashMap` | 按插入顺序排列 | 需要保持存取顺序,如 LRU 缓存 | | `TreeMap` | 按 key 自然排序 | 需要按键排序输出 | | `ConcurrentHashMap` | 线程安全 | 多线程环境共享 Map | ## 五、实战踩坑总结 1. 反向查询频繁时,预先建反向 Map,别每次都全表遍历。 2. 一个 key 要对应多个值,value 就用 `List`/`Set`,别硬塞逗号拼接的字符串。 3. `computeIfAbsent`、`getOrDefault`、`merge` 这些新方法能少写很多 if-else,值得熟悉。 4. 用中文/英文做 key 时注意 `equals` 比较,常量写前面(`"JSP".equals(value)`)避免 value 为 null 时空指针。 ## 写在最后 经过这几个案例我最大的体会是:**Map 不只是一个容器,而是一种「索引思维」**。正向查快、反向查慢,那我就为反向也建一个索引;一个 key 要对应多条记录,那值就用集合。把这点想通,Map 在实际项目里怎么用就清楚了。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 11:02:41

小白程序员必备:掌握这三项能力,轻松拥抱大模型时代!

本文探讨了在AI工具泛滥的时代&#xff0c;单纯“会用工具”并不等于“有本事”。文章指出工具是放大器&#xff0c;而非决定性因素&#xff0c;并分析了工具的三次折旧现象。强调AI参与率并非关键&#xff0c;真正重要的是站在判断层&#xff0c;具备问对题、认得出错、让AI融…

作者头像 李华
网站建设 2026/10/29 11:01:34

【算法拾光】双指针|两数之和 II - 输入有序数组 + 三数之和

题目 1&#xff1a;两数之和 II - 输入有序数组 链接&#xff1a;167. 两数之和 II - 输入有序数组 - 力扣&#xff08;LeetCode&#xff09; 题目分析 给你一个下标从 1 开始的整数数组 numbers&#xff0c;该数组已按非递减顺序排列。请你从数组中找出满足相加之和等于目标…

作者头像 李华
网站建设 2026/10/29 10:59:28

Agent开发:普通人逆袭高薪赛道,错过等三年!收藏必备

Agent开发是未来3年最值得普通人冲的技术岗&#xff0c;门槛可控&#xff0c;缺口极大&#xff0c;薪资断层领先&#xff0c;且不被AI替代。它不同于传统的AI岗位&#xff0c;而是应用层落地的智能体开发&#xff0c;核心是让AI自主思考、拆解任务、调用工具&#xff0c;完成完…

作者头像 李华
网站建设 2026/10/29 10:59:11

Agent评测可落地体系

Agent评测可落地体系&#xff1a;方法、步骤与工具 以下内容对齐阿里、腾讯、字节、百度等大厂公开的Agent评测方法论与开源工具链&#xff0c;全部为可直接落地的工程化方案&#xff0c;而非纯学术理论。 一、核心评测方法论&#xff08;四层全链路范式&#xff09; 大厂普…

作者头像 李华
网站建设 2026/10/29 10:57:36

Beyond Single‑Model Injection 论文总结

> 说明:arXiv摘要页面只公开**Abstract**,未直接提供 Introduction、Conclusion 完整文本;公开的网页摘要仅能拿到Abstract原文。下面完成:文章概要、创新点、Abstract中英对照;并标注Introduction/Conclusion获取方式。输出完整Markdown文档。 # Beyond Single‑Mode…

作者头像 李华