用set集合配合实体类实现抽奖组件,核心是利用set去重特性管理奖品或用户:奖品池去重靠重写equals/hashcode防止重复添加;中奖去重靠hashset记录已中用户并校验;抽奖需结合list随机打乱或索引抽取,实体类须正确实现equals与hashcode。

用 Set 集合配合面向对象实体类实现抽奖组件,核心在于利用 Set 的天然去重特性管理奖品或中奖用户,同时通过封装实体类提升可读性与扩展性。关键不是简单塞数据,而是明确“对谁去重”——是奖品不重复发放?还是同一用户不能中多次?下面分场景说明。
奖品池去重:避免重复添加相同奖品
适用于预设固定奖品列表(如一等奖1个、二等奖3个),需防止配置时误加重复奖品。
- 定义奖品实体类,重写 equals 和 hashCode,依据奖品 ID 或名称判断是否相同
- 使用 HashSet
存储奖品池,add() 自动过滤重复 - 示例:若两次 new Prize("iPhone15", 8999) 且 equals/hashCode 基于 name 实现,则第二次 add 失败,size 不变
中奖结果去重:确保同一用户不中多次
更常见需求——抽奖过程中,用户可能多次参与,但只允许中一次奖。
- 定义用户实体类(如 User{id, name}),按 userId 重写 equals/hashCode
- 用 HashSet
记录已中奖用户;每次抽中前先 check contains,再决定是否计入结果 - 也可用 Set
存 userId 字符串,轻量但牺牲类型安全和后续扩展(如需查用户完整信息)
抽奖逻辑与 Set 的协同设计
Set 本身不提供随机性,需结合其他机制完成“随机抽取+去重保障”:
- 将待抽名单(List
)转为 ArrayList,用 Collections.shuffle() 打乱,再遍历 + set.add() 尝试加入中奖集合 - 或用 while 循环:随机取索引 → 获取用户 → set.add() → 检查返回值(true 表示新增成功,即未中过)→ 达到目标人数退出
- 注意:不要直接在 HashSet 上 randomElement(Java 不支持),必须借助 List 或 Stream.toList() 临时转换
实体类设计要点(以 User 为例)
这是去重生效的前提,常被忽略:
- 必须重写 equals():比较关键字段(如 id),不能依赖默认的内存地址判断
- 必须重写 hashCode():保证 equals 为 true 时 hashCode 一定相等,否则 HashSet 查找失效
- 推荐用 IDE 自动生成(如 IntelliJ 的 Alt+Insert → “equals and hashCode”),选 id 字段即可
- 实体类建议设为 final,字段 private,提供必要 getter,避免运行时状态被意外修改影响 Set 行为











