在Java集合框架的学习道路上,实际项目应用是检验知识掌握程度的最佳方式。今天我们将通过两个完整的系统案例——投票统计系统和图书管理系统,来深入探索HashMap和ArrayList在真实场景中的应用技巧。
案例一:投票统计系统 - HashMap在实时统计中的威力
系统设计理念
投票统计系统是一个典型的实时数据统计应用,它需要高效地记录和更新候选人的得票数,并能够快速找出获胜者。这种模式在选举系统、问卷调查、热门投票等场景中有着广泛的应用。
完整系统架构
public class VotingSystem {
private static HashMap<String, Integer> votes = new HashMap<>();
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("=== 投票统计系统 ===");
System.out.println("请输入候选人姓名进行投票(输入'结果'查看统计结果,输入'结束'退出系统)");
while (true) {
System.out.print("请输入候选人姓名: ");
String candidate = scanner.nextLine().trim();
if (candidate.equalsIgnoreCase("结束")) {
break;
} else if (candidate.equalsIgnoreCase("结果")) {
displayResults();
} else if (!candidate.isEmpty()) {
voteForCandidate(candidate);
}
}
System.out.println("投票结束!");
displayResults();
}
// ... 其他方法
}
核心算法深度解析
1. 智能投票处理
private static void voteForCandidate(String candidate) {
votes.put(candidate, votes.getOrDefault(candidate, 0) + 1);
System.out.println("已为 " + candidate + " 投票!");
}
技术亮点:
- getOrDefault()方法优雅处理新候选人
- 原子性操作保证数据一致性
- 即时反馈提升用户体验
2. 实时统计与胜者判定
private static void displayResults() {
if (votes.isEmpty()) {
System.out.println("暂无投票数据!");
return;
}
System.out.println("\n=== 投票统计结果 ===");
String highestCandidate = null;
int highestVotes = 0;
for (Map.Entry<String, Integer> entry : votes.entrySet()) {
String candidate = entry.getKey();
int voteCount = entry.getValue();
System.out.println(candidate + ": " + voteCount + " 票");
if (voteCount > highestVotes) {
highestVotes = voteCount;
highestCandidate = candidate;
}
}
System.out.println("\n得票最高的候选人是: " + highestCandidate + ",共 " + highestVotes + " 票");
System.out.println();
}
算法优化点:
- 单次遍历同时完成统计和胜者查找
- 时间复杂度O(n),空间复杂度O(1)
- 处理平局情况(当前实现会选择最先达到最高票的候选人)
用户体验设计
交互流程优化
System.out.println("请输入候选人姓名进行投票(输入'结果'查看统计结果,输入'结束'退出系统)");
设计思考:
- 清晰的指令提示
- 大小写不敏感的命令识别
- 实时结果查看功能
- 友好的退出机制
运行示例
=== 投票统计系统 ===
请输入候选人姓名进行投票(输入'结果'查看统计结果,输入'结束'退出系统)
请输入候选人姓名: 张三
已为 张三 投票!
请输入候选人姓名: 李四
已为 李四 投票!
请输入候选人姓名: 张三
已为 张三 投票!
请输入候选人姓名: 结果
=== 投票统计结果 ===
张三: 2 票
李四: 1 票
得票最高的候选人是: 张三,共 2 票
请输入候选人姓名: 结束
投票结束!
系统扩展建议
1. 多维度统计
// 添加时间戳记录
private static HashMap<String, List<LocalDateTime>> voteTimestamps = new HashMap<>();
// 添加地域信息
private static HashMap<String, String> voterLocation = new HashMap<>();
2. 数据持久化
// 保存投票数据到文件
private static void saveVotesToFile() {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("votes.dat"))) {
oos.writeObject(votes);
} catch (IOException e) {
e.printStackTrace();
}
}
案例二:图书管理系统 - ArrayList在数据管理中的全面应用
系统架构设计
图书管理系统是一个典型的信息管理系统,涉及数据的增删改查、统计分析和排序展示。这个案例完整展示了ArrayList在管理对象集合时的各种操作技巧。
面向对象设计
Book类 - 数据模型封装
class Book {
private String title;
private String author;
private double price;
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
// Getters
public String getTitle() { return title; }
public String getAuthor() { return author; }
public double getPrice() { return price; }
@Override
public String toString() {
return String.format("书名: %s, 作者: %s, 价格: %.2f", title, author, price);
}
}
设计原则体现:
- 封装性:私有字段+公共getter
- 不变性:没有setter方法,对象创建后不可变
- 可读性:重写toString()方法
功能模块详解
1. 主控模块 - 菜单驱动系统
public static void main(String[] args) {
while (true) {
System.out.println("\n=== 图书管理系统 ===");
System.out.println("1. 添加图书信息");
System.out.println("2. 根据书名删除图书信息");
System.out.println("3. 查找某本书的价格");
System.out.println("4. 输出所有图书的平均价格");
System.out.println("5. 按价格从低到高排序并输出图书信息");
System.out.println("0. 退出系统");
System.out.print("请选择操作: ");
int choice = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
switch (choice) {
case 1 -> addBook();
case 2 -> deleteBook();
case 3 -> findBookPrice();
case 4 -> calculateAveragePrice();
case 5 -> sortAndDisplayBooks();
case 0 -> {
System.out.println("感谢使用图书管理系统!");
return;
}
default -> System.out.println("无效选择,请重新输入!");
}
}
}
2. 图书添加 - 数据录入
private static void addBook() {
System.out.print("请输入书名: ");
String title = scanner.nextLine();
System.out.print("请输入作者: ");
String author = scanner.nextLine();
System.out.print("请输入价格: ");
double price = scanner.nextDouble();
scanner.nextLine(); // 消耗换行符
books.add(new Book(title, author, price));
System.out.println("图书信息添加成功!");
}
输入处理技巧:
- 混合输入类型的安全处理
- 换行符的精确控制
- 用户反馈的及时提供
3. 图书删除 - 精确查找
private static void deleteBook() {
System.out.print("请输入要删除的图书书名: ");
String title = scanner.nextLine();
boolean found = false;
for (int i = 0; i < books.size(); i++) {
if (books.get(i).getTitle().equalsIgnoreCase(title)) {
books.remove(i);
found = true;
System.out.println("图书信息删除成功!");
break;
}
}
if (!found) {
System.out.println("未找到该书名的图书!");
}
}
搜索优化:
- 大小写不敏感比较
- 线性搜索的及时中断
- 完整的状态反馈
4. 价格查询 - 信息检索
private static void findBookPrice() {
System.out.print("请输入要查找的图书书名: ");
String title = scanner.nextLine();
boolean found = false;
for (Book book : books) {
if (book.getTitle().equalsIgnoreCase(title)) {
System.out.printf("图书《%s》的价格为: %.2f\n", title, book.getPrice());
found = true;
break;
}
}
if (!found) {
System.out.println("未找到该书名的图书!");
}
}
增强型for循环优势:
- 代码简洁性
- 避免索引错误
- 更好的可读性
5. 统计分析 - 数据洞察
private static void calculateAveragePrice() {
if (books.isEmpty()) {
System.out.println("暂无图书信息!");
return;
}
double sum = 0;
for (Book book : books) {
sum += book.getPrice();
}
double average = sum / books.size();
System.out.printf("所有图书的平均价格为: %.2f\n", average);
}
边界情况处理:
- 空集合检测
- 浮点数精度控制
- 格式化输出
6. 智能排序 - 数据展示
private static void sortAndDisplayBooks() {
if (books.isEmpty()) {
System.out.println("暂无图书信息!");
return;
}
// 使用Comparator按价格升序排序
books.sort(Comparator.comparingDouble(Book::getPrice));
System.out.println("按价格从低到高排序的图书信息:");
for (int i = 0; i < books.size(); i++) {
System.out.println((i + 1) + ". " + books.get(i));
}
}
现代排序技术:
- 方法引用语法糖
- Comparator的链式操作
- 清晰的排序逻辑
系统运行示例
=== 图书管理系统 ===
1. 添加图书信息
2. 根据书名删除图书信息
3. 查找某本书的价格
4. 输出所有图书的平均价格
5. 按价格从低到高排序并输出图书信息
0. 退出系统
请选择操作: 1
请输入书名: Java编程思想
请输入作者: Bruce Eckel
请输入价格: 89.50
图书信息添加成功!
请选择操作: 5
按价格从低到高排序的图书信息:
1. 书名: 数据结构, 作者: 严蔚敏, 价格: 45.00
2. 书名: Java编程思想, 作者: Bruce Eckel, 价格: 89.50
技术对比与选型指南
HashMap vs ArrayList 适用场景
|
特性 |
HashMap |
ArrayList |
|
数据访问 |
键值对快速访问 |
索引顺序访问 |
|
性能 |
O(1)查找 |
O(1)随机访问,O(n)查找 |
|
排序 |
不保持顺序 |
保持插入顺序 |
|
内存 |
较高(存储哈希表) |
较低(连续数组) |
|
适用场景 |
投票统计、缓存、字典 |
图书管理、日志记录、列表展示 |
设计模式应用
1. 数据传输对象模式(DTO)
Book类就是一个典型的DTO,用于在不同层之间传输数据。
2. 控制器模式
主菜单系统充当控制器,协调各个功能模块。
性能优化与最佳实践
内存管理优化
// 设置ArrayList初始容量
private static ArrayList<Book> books = new ArrayList<>(100);
// 使用trimToSize释放多余空间
books.trimToSize();
并发安全考虑
// 多线程环境使用CopyOnWriteArrayList
private static List<Book> books = new CopyOnWriteArrayList<>();
// 或者使用Collections.synchronizedList
private static List<Book> books = Collections.synchronizedList(new ArrayList<>());
代码质量保证
// 输入验证
private static void addBook() {
System.out.print("请输入书名: ");
String title = scanner.nextLine().trim();
if (title.isEmpty()) {
System.out.println("书名不能为空!");
return;
}
// ... 其他验证
}
扩展功能设想
投票系统扩展
- 投票限制:IP限制、时间限制
- 实时图表:使用JFreeChart生成统计图表
- 数据导出:Excel、PDF格式导出
图书管理系统扩展
- ISBN支持:国际标准书号管理
- 借阅系统:读者管理和借阅记录
- Web界面:Spring Boot + Thymeleaf开发
- 数据库集成:MySQL持久化存储
总结
通过这两个完整的系统案例,我们深入掌握了:
- HashMap的核心应用:键值对存储、快速查找、实时统计
- ArrayList的全面操作:增删改查、排序、统计、遍历
- 面向对象设计原则:封装、单一职责、开闭原则
- 用户体验设计:交互流程、错误处理、反馈机制
- 系统架构思维:模块划分、数据流设计、扩展性考虑
这些知识不仅适用于投票和图书管理场景,还可以迁移到各种信息管理系统、数据统计应用和业务处理平台中。掌握这些核心技能,将为你的Java开发之路奠定坚实的基础。


2866

被折叠的 条评论
为什么被折叠?



