用HashMap统计投票最直接,需统一处理候选人名字并用getOrDefault()安全计票;保留原始票记录便于审计;排序用Stream.sorted()更可靠;并发场景须用compute()保证原子性。

用 HashMap 存候选人和票数最直接
投票统计本质是「名字 → 票数」的映射,HashMap 天然适合。别一上来就搞 TreeMap 或自定义类——除非真要按得票排序输出,否则纯属增加复杂度。
注意点:
-
put()会覆盖旧值,计票必须用put(key, map.getOrDefault(key, 0) + 1) - 候选人名字含空格、大小写不敏感?得提前
.trim().toLowerCase()统一处理,否则"张三"和"张三 "算两个人 - 避免在循环里反复调用
get()再判null,用getOrDefault()更安全简洁
Mapvotes = new HashMap<>(); String candidate = "李四".trim().toLowerCase(); votes.put(candidate, votes.getOrDefault(candidate, 0) + 1);
用 ArrayList 存原始票记录便于查重和审计
只存最终结果不够健壮。真实场景中常需回溯「谁投了谁」「有没有重复投票」,这时得保留原始票数据。
建议结构:ArrayList,其中 VoteRecord 是个简单类,至少含 voterId(如学号)和 candidate 字段。
立即学习“Java免费学习笔记(深入)”;
关键操作:
- 插入前先用
stream().anyMatch()检查voterId是否已存在,防止刷票 - 查某人投票记录:用
list.stream().filter(r -> r.voterId.equals("2023001")).findFirst() - 不推荐用
LinkedList——随机访问少,但按 ID 查时仍要遍历,没优势
统计结果排序别硬写冒泡,用 Stream.sorted() 更可靠
按票数降序排候选人,不是为了炫技,而是方便一眼看出前三名。手写排序容易出错,且 Java 8+ 的流式写法清晰又不易漏边界条件。
示例逻辑:
- 把
entrySet()转成流,用sorted(Map.Entry.comparingByValue().reversed()) - 注意:如果票数相同,
reversed()不保证姓名顺序,需要链式加thenComparingByKey() - 最后用
limit(3)截取前三,比手动遍历 + 计数器更直观
votes.entrySet().stream()
.sorted(Map.Entry.comparingByValue().reversed()
.thenComparing(Map.Entry::getKey))
.limit(3)
.forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));
并发场景下 ConcurrentHashMap 不能只换类名
如果系统要支持多线程同时投票(比如 Web 接口),光把 HashMap 换成 ConcurrentHashMap 不够——getOrDefault() + put() 这两步不是原子操作,仍可能丢票。
正确做法:
- 用
compute()方法:votes.compute(candidate, (k, v) -> (v == null ? 0 : v) + 1) - 或改用
ConcurrentHashMap.newKeySet()配合计数器 Map,但多数简易系统用不到 - 别迷信
synchronized块锁整个 map——吞吐量暴跌,小项目不如直接加读写锁或用ReentrantLock
真正上线前,拿 ExecutorService 启 100 个线程并发投同一人,跑几轮再看总数对不对,比看文档管用。










