Collections.shuffle()基于Fisher-Yates算法原地随机打乱List,保证均匀分布;仅支持List,需可变实例;可传入Random种子实现可重现结果;非List集合需先转List再shuffle;全量重排适合随机采样,单元素获取用nextInt更高效。

Collections.shuffle() 是 Java 中最简单、最可靠的集合随机打乱方法,它基于 Fisher-Yates 洗牌算法,能保证每个排列出现的概率均等。
直接对 List 进行原地打乱
该方法只支持 List 接口(如 ArrayList、LinkedList),不支持 Set 或 Map。调用后原集合顺序被修改,无需返回新集合。
- 确保传入的是可变的 List(如 new ArrayList(original)),不可变列表(如 List.of()、Arrays.asList() 返回的固定大小列表)会抛 UnsupportedOperationException
- 若需保留原顺序,先复制一份:List<String> shuffled = new ArrayList(original); Collections.shuffle(shuffled);
- 默认使用系统默认的随机源(new Random()),适合一般场景
使用自定义 Random 实现可重现的随机结果
当需要测试稳定、调试复现或种子控制时,可传入带种子的 Random 对象:
- Collections.shuffle(list, new Random(123L)); —— 每次运行都产生相同打乱顺序
- 适合单元测试中验证“随机”逻辑是否按预期影响后续流程(比如抽奖、抽题、洗牌游戏)
- 注意:多线程环境下建议为每个线程创建独立 Random 实例,避免竞争
对非 List 集合实现“伪随机重组”
Set、Queue 等不保证顺序的集合本身无“顺序”概念;若需随机遍历或取样,可转为 List 再 shuffle:
- List<T> temp = new ArrayList<>(set); Collections.shuffle(temp);
- 再通过 temp.get(0) 取随机元素,或 temp.subList(0, k) 实现随机采样
- Map 的键/值也可先转为 List:new ArrayList<>(map.keySet()),再 shuffle
常见误区与注意事项
不是所有“随机”需求都适合 shuffle —— 它是全量重排,开销随集合大小线性增长。
- 仅需一个随机元素?用 list.get(random.nextInt(list.size())) 更高效
- 需要随机且不重复地选多个?shuffle 后取前 k 个,比反复 random.nextInt() + 去重更简洁可靠
- 若 List 包含 null 元素或自定义对象,不影响 shuffle 行为,但要注意排序或比较逻辑是否依赖顺序

















