collections.shuffle 是基于 fisher-yates 算法的公平随机打乱工具,需用可修改的 arraylist 调用,支持固定种子测试与 securerandom 安全场景,arraylist 性能最优。

Collections.shuffle 是 Java 中最直接、最可靠的列表打乱工具,一行代码就能完成公平随机重排,不需要手写循环、不依赖排序陷阱、也不拼接字符串。它基于 Fisher-Yates 算法,保证每种排列出现概率完全均等,适用于抽奖、题库抽题、推荐位轮播等真实业务场景。
必须用可修改的 ArrayList 才能调用
shuffle 只接受支持 set() 和 get() 的 List 实现。常见错误是直接传入 Arrays.asList("A", "B", "C")——它返回的是固定大小的内部列表,调用时会抛 UnsupportedOperationException。
- 正确做法:用
new ArrayList(Arrays.asList(...))包一层再 shuffle - Set 或 Map 需先转成 List:
new ArrayList(mySet)或new ArrayList(map.keySet()) - 数组(如
String[])不能直传,必须先转为 List - 空列表或单元素列表可安全调用,不报错也不做任何操作,这是设计行为
抽奖和随机采样:打乱一次,取前 N 个就够了
不需要 while 循环抽、不用去重校验、不担心重复中奖——打乱后取前 N 个就是天然公平的随机结果。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 中奖名单:
shuffledList.subList(0, Math.min(n, shuffledList.size())) - 题库抽 5 道题:shuffle 后取前 5 个,顺序无偏、无重复、无遗漏
- 避免“抽一个删一个再重 shuffle”:那会破坏 Fisher-Yates 的等概率保证
测试要可重现,生产要真随机
默认 shuffle 使用系统时间作种子,毫秒级密集调用可能撞上相同序列;而单元测试、抽奖审计、游戏存档需要每次跑出一样结果。
- 测试写法:
Collections.shuffle(list, new Random(123L)),固定种子确保输出一致 - 生产保持默认:
Collections.shuffle(list)即可,Java 17+ 默认使用 LXM 算法,均匀性优于旧版 - 高安全要求场景可换用
SecureRandom,但注意初始化可能阻塞
性能差异大:ArrayList 快,LinkedList 慢
shuffle 内部会根据 List 类型自动优化路径:
- 对
ArrayList(实现RandomAccess):原地交换,O(n) 时间 + O(1) 空间 - 对
LinkedList:先转Object[]打乱,再逐个写回,避免链表遍历开销;十万级数据下性能可能差两个数量级 - 元素数 ≤ 5 时统一走轻量路径,无需担心小集合开销
- 高频洗牌场景建议优先选用
ArrayList;若业务强依赖LinkedList的插入/删除特性,需评估是否真有必要频繁 shuffle
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










