在Java里如何实现简易投票统计系统_Java集合实践说明

用HashMap统计投票最直接,需统一处理候选人名字并用getOrDefault()安全计票;

保留原始票记录便于审计;排序用Stream.sorted()更可靠;并发场景须用compute()保证原子性。

HashMap 存候选人和票数最直接

投票统计本质是「名字 → 票数」的映射,HashMap 天然适合。别一上来就搞 TreeMap 或自定义类——除非真要按得票排序输出,否则纯属增加复杂度。

注意点:

  • put() 会覆盖旧值,计票必须用 put(key, map.getOrDefault(key, 0) + 1)
  • 候选人名字含空格、大小写不敏感?得提前 .trim().toLowerCase() 统一处理,否则 "张三""张三 " 算两个人
  • 避免在循环里反复调用 get() 再判 null,用 getOrDefault() 更安全简洁
Map votes = new HashMap<>();
String candidate = "李四".trim().toLowerCase();
votes.put(candidate, votes.getOrDefault(candidate, 0) + 1);

ArrayList 存原始票记录便于查重和审计

只存最终结果不够健壮。真实场景中常需回溯「谁投了谁」「有没有重复投票」,这时得保留原始票数据。

建议结构:ArrayList,其中 VoteRecord 是个简单类,至少含 voterId(如学号)和 candidate 字段。

关键操作:

  • 插入前先用 stream().anyMatch() 检查 voterId 是否已存在,防止刷票
  • 查某人投票记录:用 list.stream().filter(r -> r.voterId.equals("2025001")).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 个线程并发投同一人,跑几轮再看总数对不对,比看文档管用。