collections.rotate是java中对list原地循环移位的高效方法,通过三次反转实现o(n)时间、o(1)空间的右旋(正数)或左旋(负数),适用于滑动窗口平移和轮转调度等场景。

Collections.rotate 是 Java 集合工具类中一个轻量但高效的操作,它不创建新集合、不扩容、不复制全部元素,而是通过三次反转(reverse)在 O(n) 时间内完成循环位移。在滑动窗口和轮转调度这类需要“整体偏移+局部更新”的场景中,它比手动 remove-add 或数组拷贝更简洁、更安全。
滑动窗口:用 rotate 实现低成本窗口平移
当窗口大小固定、数据源为 ArrayList 或 ArrayDeque 时,可将新元素追加到末尾,再用 rotate 把最老元素“甩”到开头(或反之),随后截断——避免每次滑动都调用 remove(0) 导致的 O(n) 移动开销。
例如维护长度为 3 的窗口,当前为 [1,2,3],新值为 4:
- 先
list.add(4)→[1,2,3,4] - 再
Collections.rotate(list, -1)→[2,3,4,1] - 最后
list.remove(list.size() - 1)→[2,3,4]
注意:rotate 的位移量为负表示左旋(首元素移到末尾),正数表示右旋(末元素移到开头)。实际使用中建议封装成 slideWindow(List, newItem, windowSize) 方法,内部统一处理边界。
轮转调度:模拟 FCFS 轮询或任务队列重排
在简单轮转调度器(如线程池任务分发、API 请求轮询后端实例)中,若需“本轮从上次结束位置继续”,可用 rotate 将已执行项移到队尾,保持逻辑顺序不变而物理位置更新。
例如服务实例列表 ["A", "B", "C", "D"],本轮选中 "B" 处理请求:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 找到 "B" 索引(1)
-
Collections.rotate(instances, -1)→["B","C","D","A"] - 下次直接取
get(0)即可获得下一个调度目标("B" 已就位)
这种做法天然支持动态增删:新增实例只需 add 到末尾,再按需 rotate;删除则先 remove 再 rotate,无需重算偏移索引。
注意事项与性能提醒
Collections.rotate 要求传入的是支持随机访问的 List(如 ArrayList),对 LinkedList 效率极低(每次 get 都是 O(n));也不适用于不可变集合或包装视图(如 Arrays.asList() 返回的固定大小列表,rotate 可能抛 UnsupportedOperationException)。
关键点:
- 确保 list 是可修改、可随机访问的实现
- 位移量可对 list.size() 取模,避免冗余旋转(
rotate(list, k % list.size())) - 多线程环境下需自行同步,该方法本身不保证线程安全
替代思路对比:为什么不用 Stream 或 subList?
有人倾向用 stream().skip().limit() 构造新窗口,或用 subList 截取视图——前者创建新流、后者只是视图且底层 list 变化会影响视图,都不如 rotate + 原地修改来得直接可控。尤其在高频滑动(如实时指标采集)中,减少对象分配和 GC 压力更关键。
rotate 不是万能,但它在“小规模偏移 + 原地更新”这一交集里,确实是最贴切的原生方案。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










