用 HashMap 存候选人和票数最直接,因其天然支持「名字→票数」映射;避免 ArrayList 重复统计;推荐 new HashMap() 初始化,用 getOrDefault 更新票数;固定候选人可用 EnumMap;防刷票用 HashSet 记用户 ID,勿用 IP 或时间戳;找最高票需用 entrySet().stream().max() 并处理空值与平票;中文乱码多因编码不一致,需统一设为 UTF-8。

用 HashMap 存候选人和票数是最直接的做法
投票系统核心是「名字 → 票数」的映射关系,HashMap 天然适配。别用 ArrayList 存一堆重复姓名再遍历统计——性能差、易出错。
实操建议:
- 初始化时用
new HashMap(),避免用过时的Hashtable - 每次投票调用
map.put(candidate, map.getOrDefault(candidate, 0) + 1),不用手动判空 - 如果候选人固定(比如预设3人),可考虑用
EnumMap,更类型安全、略快
防止刷票得靠简单去重,不是所有场景都要数据库
简易系统通常跑在单机 JVM 内,用 HashSet 记已投票用户 ID(如学号、手机号)就够了。重点不是“防黑客”,而是避免同一人点十次提交全算数。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 把 IP 当唯一标识——局域网下多人共用一个出口 IP,会误拦
- 用时间戳做 key——精度不够或并发时重复,导致漏计
- 没清空投票记录,重启后历史数据还在,但
HashSet是内存对象,JVM 停就丢,需按需持久化
Collections.max() 找最高票要小心 null 和平票
想快速拿到票数最多的候选人?别直接对 map.values() 调 Collections.max()——它不返回是谁投的,只返回最大票数;而且如果 map 为空,会抛 NoSuchElementException。
更稳妥的做法:
- 先检查
map.isEmpty(),空则跳过统计逻辑 - 用
map.entrySet().stream().max(Map.Entry.comparingByValue()),能同时拿到人名和票数 - 平票时该返回谁?默认取
findFirst()遇到的第一个,但业务上可能要返回全部并列者,那就得用filter+collect
控制台输出中文乱码?先查 file.encoding 和终端编码
集合操作本身不会导致乱码,但打印候选人中文名时出方块,大概率是环境问题。Windows 的 CMD 默认 GBK,而 Java 源文件通常是 UTF-8。
临时解决方法(开发阶段):
- 启动 JVM 时加参数:
-Dfile.encoding=UTF-8 - IDE 运行配置里显式设置 VM options,别只改编辑器编码
- 若用
System.out.println()输出,确保终端支持 UTF-8(如 Windows Terminal、iTerm2),CMD 不推荐长期用
真实部署时,输出往往进日志文件或 Web 页面,这时乱码根源常在日志框架的 encoder 配置或 HTTP 响应头,不在集合操作本身。










