讲师中心 微信公众号
AI工具推荐 视频效率加速

图书管理系统设计与实现_集合框架(List/Map)与对象关联实战

大杰吖_8871

大杰吖_8871

发布时间:2026-02-13 13:03:29

|

899人浏览过

|

来源于php中文网

原创

应使用 ArrayList 而非 LinkedList:因图书增删集中在尾部、查询频繁,ArrayList 的 O(1) 随机访问和缓存友好性更优;LinkedList 的指针开销在图书对象较小时反而拖慢遍历。

图书管理系统设计与实现_集合框架(list/map)与对象关联实战

为什么用 ArrayList 而不是 LinkedList 存图书列表

图书管理系统里,图书增删集中在尾部(比如批量导入、新书上架),查询多于插入中间位置。这时候 ArrayList 的随机访问 O(1) 和缓存友好性明显胜出;LinkedList 的每个节点指针开销反而拖慢遍历和迭代——尤其当图书对象本身不大时,指针成本占比更高。

常见错误是看到“链表适合频繁增删”就直接套用,但没注意增删位置:图书列表极少在中间插入(比如第 37 本前插一本),真要那样,不如先用 ArrayList + add(index, element),再观察性能瓶颈是否真的来自这一步。

  • 新增图书一律用 list.add(book),别写 list.add(list.size(), book) —— 效果一样,后者多一次计算还干扰阅读
  • 避免在 for 循环里反复调用 list.size() 判断长度,JVM 一般会优化,但明确写成 int n = list.size(); for (int i = 0; i 更稳
  • 如果后期真需要按 ISBN 快速查某本书,别硬扛着遍历 ArrayList,立刻补一层 Map<String, Book>,键用 book.getIsbn()

HashMap 的 key 为什么必须重写 hashCode() 和 equals()

图书借阅模块常用 Map<String, List<Book>> 按作者归类,或 Map<String, Book> 按 ISBN 查书。一旦 key 是自定义对象(比如用 BookId 类封装 ISBN),不重写这两个方法,get() 就永远返回 null——因为默认的 hashCode() 返回的是内存地址哈希,两次 new 出来的对象哪怕内容相同,哈希值也不同。

典型报错现象:map.put(new BookId("978-7-02-000000-0"), book); 之后 map.get(new BookId("978-7-02-000000-0")) 拿不到值,调试发现 size 是 1,但 get 失败。

  • IDE 自动生成的 hashCode()/equals() 只要覆盖所有参与逻辑相等判断的字段(比如 ISBN 字符串)就行,别漏掉 null 检查
  • 别用可变字段做 key 的计算依据(例如把 Book.title 当 key 字段又允许改标题),否则 map 内部桶位置错乱,数据就丢了
  • 如果 key 纯是字符串(如直接用 isbn 当 key),不用额外处理——String 已经重写好了

遍历借阅记录 Map 时,该用 entrySet() 还是 keySet()

展示“张三借了哪些书”这类功能,代码常写成 for (String userId : borrowMap.keySet()) { List<Book> books = borrowMap.get(userId); ... }。这看起来自然,但每次 get() 都是一次哈希查找,时间复杂度从 O(n) 变成 O(n × 平均查找耗时),数据量大时肉眼可感卡顿。

真实场景中,借阅记录 Map 可能有上千个用户,每个用户平均借 3–5 本书。用 entrySet() 直接拿到键值对,既少一次哈希定位,又避免重复构造 Iterator。

  • 优先写 for (Map.Entry<String, List<Book>> entry : borrowMap.entrySet()),然后用 entry.getKey() 和 entry.getValue()
  • 如果只用 value(比如统计所有借出图书总数),用 values() 最干净:int total = borrowMap.values().stream().mapToInt(List::size).sum();
  • 千万别在循环里修改正在遍历的 map(比如边查边删过期记录),会抛 ConcurrentModificationException;要删得先收集 key,再统一 removeAll()

List 和 Map 嵌套太深时,怎么避免 NullPointerException

Map<String, Map<String, List<Book>>> userBooksByYear 这种三层结构很常见(用户 → 年份 → 图书列表),但每层都可能为 null:用户没借过书、某年没借书、甚至年份 key 根本不存在。直接链式调用 userBooksByYear.get(userId).get("2024").size() 必崩。

不是靠一堆 if 判断,而是用“容器即空值”的思维:让每一层缺失时返回空集合,而不是 null。Java 8+ 推荐用 computeIfAbsent() 初始化,比手写 if-null-put 清晰得多。

  • 初始化嵌套 map:userBooksByYear.computeIfAbsent(userId, k -> new HashMap<>()).computeIfAbsent("2024", k -> new ArrayList<>()).add(book);
  • 读取时仍要防第一层 null:Map<String, List<Book>> yearMap = userBooksByYear.get(userId); 后加一句 if (yearMap == null) return Collections.emptyList();
  • 别依赖 IDE 自动补全的 Objects.requireNonNull(),它只是提前报错,没解决空值语义问题

嵌套越深,初始化责任越往前移——不是等用到才检查,而是在第一次 put 时就确保路径畅通。这点容易被忽略,直到线上查半天才发现某类用户数据根本进不了第三层。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6339

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1678

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1738

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2684

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6064

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

5649

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

7314

2024.03.22

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

60

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn