Collections.reverse()仅支持List,时间复杂度O(n),原地反转;Collections.shuffle()仅支持List,需指定种子才能复现结果;二者均不支持Set、Map、数组及并发安全,且均为就地修改操作。

reverse 只能反转 List,不能用于 Set 或 Map
Java 的 Collections.reverse() 是一个静态方法,作用对象严格限定为 List 接口实现类(如 ArrayList、LinkedList),对 Set、Map 或数组直接调用会编译失败。
- 传入
null会抛出NullPointerException - 内部采用双向指针原地交换,时间复杂度 O(n),不创建新集合
- 若 List 包含不可变元素(如
String)没问题;但若含可变对象,仅改变顺序,不修改对象本身
ArrayListlist = new ArrayList<>(Arrays.asList("a", "b", "c")); Collections.reverse(list); // ✅ 正确:list 变为 ["c", "b", "a"] // Collections.reverse(new HashSet<>()); // ❌ 编译错误:HashSet 不是 List
shuffle 使用默认随机源,结果不可复现
Collections.shuffle() 默认使用 new Random() 实例,每次运行顺序都不同。若需测试稳定或回放行为(比如单元测试、日志重演),必须显式传入带种子的 Random。
- 同样只支持
List,不支持其他集合类型 - 底层调用 Fisher–Yates 洗牌算法,保证每个排列等概率
- 若 List 为空或只有一个元素,操作无效果,也不报错
- 注意:若 List 是由
Arrays.asList()创建的固定大小列表,shuffle 仍有效;但若底层数组被外部修改,可能引发ConcurrentModificationException
ArrayListnums = new ArrayList<>(Arrays.asList(1, 2, 3, 4)); Collections.shuffle(nums, new Random(42)); // ✅ 固定种子,每次 shuffle 结果相同 // Collections.shuffle(nums); // ❌ 随机性不可控
reverse 和 shuffle 都不支持并发安全
这两个方法均假设输入 List 在操作期间不被其他线程修改。若在多线程环境中直接对非线程安全的 ArrayList 调用,可能抛出 ConcurrentModificationException,或产生不可预期顺序。
- 没有内置同步机制,也不会返回新副本
- 如需线程安全场景,应先加锁,或改用
Collections.synchronizedList()包装,但注意包装后仍需手动同步迭代操作 - 另一种思路是用不可变集合(如
ImmutableListfrom Guava)+ 创建新列表再操作,避免副作用
替代方案:Stream API 无法直接 reverse,但可间接实现
Java 8+ 的 Stream 不提供 reverse() 方法,因为流设计为单向消费。若坚持函数式风格,需转成数组或收集为新 List 再处理:
立即学习“Java免费学习笔记(深入)”;
-
list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), l -> { Collections.reverse(l); return l; }))—— 原地改,不推荐 - 更安全写法:
IntStream.range(0, list.size()).mapToObj(i -> list.get(list.size() - 1 - i)).collect(Collectors.toList()) -
shuffle无 Stream 等价方法,必须回到Collections工具类
真正容易被忽略的是:reverse 和 shuffle 都是「就地修改」操作,如果原始引用被多处持有,所有地方看到的都是已变顺序——这不是 bug,是设计使然,但常被当作意外副作用。










