ZetCode

Java Collections.rotate 方法

上次修改时间:2025 年 4 月 20 日

Collections.rotate 方法是一个用于旋转 List 中元素的实用工具。旋转操作根据指定的距离将元素在列表中向前或向后移动。此操作对于循环移位和重新排列非常有用。

该方法是 Java 集合框架的一部分。它适用于任何 List 实现。旋转可以在原地执行,而无需创建新的列表。负距离向后旋转,而正距离向前旋转。

Collections.rotate 概述

rotate 方法接受一个 List 和一个距离参数。它通过将每个元素移动到位置 (index + distance) % list.size() 来旋转元素。此操作效率很高,通常在线性时间内运行。

关键特性包括支持向前和向后旋转。该方法修改原始列表,而不是返回一个新列表。它适用于任何 List 实现,包括 ArrayList 和 LinkedList。

基本向前旋转

此示例演示了列表的基本向前旋转。我们创建一个整数 ArrayList,并将其旋转 2 个位置。旋转将元素移动到更高的索引,并在需要时环绕到开头。

BasicForwardRotation.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BasicForwardRotation {

    public static void main(String[] args) {
        
        List<Integer> numbers = new ArrayList<>();
        Collections.addAll(numbers, 1, 2, 3, 4, 5);
        
        System.out.println("Original list: " + numbers);
        
        // Rotate forward by 2 positions
        Collections.rotate(numbers, 2);
        
        System.out.println("After rotation: " + numbers);
    }
}

此代码显示了简单的向前旋转。原始列表 [1, 2, 3, 4, 5] 在旋转后变为 [4, 5, 1, 2, 3]。当元素到达列表的末尾时,它们会环绕到开头。

旋转距离 (2) 决定了每个元素向前移动多少个位置。该操作在原地执行,修改原始列表。

基本向后旋转

此示例演示了使用负距离的向后旋转。我们将一个字符串列表向后旋转 1 个位置。负距离将元素移动到较低的索引。

BasicBackwardRotation.java
package com.zetcode;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class BasicBackwardRotation {

    public static void main(String[] args) {
        
        List<String> colors = Arrays.asList("Red", "Green", "Blue", "Yellow");
        
        System.out.println("Original list: " + colors);
        
        // Rotate backward by 1 position
        Collections.rotate(colors, -1);
        
        System.out.println("After rotation: " + colors);
    }
}

此代码将列表向后旋转 1 个位置。原始列表 [Red, Green, Blue, Yellow] 变为 [Green, Blue, Yellow, Red]。第一个元素环绕到末尾。

负旋转距离与正旋转距离类似,但在相反的方向上。绝对值决定了要移动多少个位置。

旋转距离大于列表大小

当旋转距离超过列表大小时,它实际上会取模列表大小。此示例显示了按大于列表长度的距离旋转。结果等同于按余数旋转。

LargeRotationDistance.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class LargeRotationDistance {

    public static void main(String[] args) {
        
        List<Character> letters = new ArrayList<>();
        Collections.addAll(letters, 'A', 'B', 'C', 'D');
        
        System.out.println("Original list: " + letters);
        
        // Rotate by distance larger than list size
        Collections.rotate(letters, 5);
        
        System.out.println("After rotation: " + letters);
    }
}

此示例将一个 4 元素的列表旋转 5 个位置。由于 5 mod 4 等于 1,因此结果等同于旋转 1 个位置。列表 [A, B, C, D] 变为 [D, A, B, C]。

取模运算确保距离始终在范围内。这使得该方法可以安全地用于任何整数距离值。

旋转子列表

rotate 方法可与子列表视图一起使用,以仅旋转列表的一部分。此示例演示了在更大的列表中旋转一个 3 元素的片段。列表的其余部分保持不变。

SublistRotation.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SublistRotation {

    public static void main(String[] args) {
        
        List<Integer> numbers = new ArrayList<>();
        Collections.addAll(numbers, 1, 2, 3, 4, 5, 6, 7);
        
        System.out.println("Original list: " + numbers);
        
        // Rotate elements 2-4 (inclusive) by 1 position
        Collections.rotate(numbers.subList(2, 5), 1);
        
        System.out.println("After sublist rotation: " + numbers);
    }
}

此代码旋转索引 2-4 (3, 4, 5) 处的元素 1 个位置。原始列表 [1, 2, 3, 4, 5, 6, 7] 变为 [1, 2, 5, 3, 4, 6, 7]。仅影响指定的子列表。

子列表旋转对于操作较大列表的片段很有用。此操作保持子列表外部元素的相对顺序。

旋转 LinkedList

rotate 方法适用于不同的 List 实现。此示例演示了旋转 LinkedList。对于某些操作,LinkedLists 的旋转效率可能高于 ArrayLists。

LinkedListRotation.java
package com.zetcode;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class LinkedListRotation {

    public static void main(String[] args) {
        
        List<String> words = new LinkedList<>();
        Collections.addAll(words, "apple", "banana", "cherry", "date");
        
        System.out.println("Original list: " + words);
        
        // Rotate LinkedList by 3 positions
        Collections.rotate(words, 3);
        
        System.out.println("After rotation: " + words);
    }
}

此示例将一个字符串 LinkedList 旋转 3 个位置。原始列表 [apple, banana, cherry, date] 变为 [banana, cherry, date, apple]。该操作的运行方式与 List 实现无关。

LinkedList 旋转可能具有与 ArrayList 旋转不同的性能特征。该方法会自动适应列表类型。

多次旋转

可以链接多次旋转以实现复杂的重新排列。此示例显示了顺序旋转如何影响列表。每次旋转都应用于列表的当前状态。

MultipleRotations.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MultipleRotations {

    public static void main(String[] args) {
        
        List<Integer> nums = new ArrayList<>();
        Collections.addAll(nums, 1, 2, 3, 4, 5, 6);
        
        System.out.println("Original list: " + nums);
        
        // First rotation
        Collections.rotate(nums, 2);
        System.out.println("After first rotation: " + nums);
        
        // Second rotation
        Collections.rotate(nums, -3);
        System.out.println("After second rotation: " + nums);
        
        // Third rotation
        Collections.rotate(nums, 4);
        System.out.println("After third rotation: " + nums);
    }
}

此示例对一个整数列表执行三次旋转。第一次向前旋转 2 个位置,第二次向后旋转 3 个位置,第三次向前旋转 4 个位置。每次旋转都基于前一个结果。

输出显示了每次旋转后列表的状态。可以组合多次旋转以实现特定的元素排列。

实际用例:旋转一副牌

此示例演示了旋转的实际应用 - 模拟洗牌。我们旋转一副牌以将某些牌移到顶部。这模仿了真实世界的扑克牌处理技术。

CardDeckRotation.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CardDeckRotation {

    public static void main(String[] args) {
        
        List<String> deck = new ArrayList<>();
        Collections.addAll(deck, "A♠", "K♠", "Q♠", "J♠", "10♠", "9♠",
                          "A♥", "K♥", "Q♥", "J♥", "10♥", "9♥");
        
        System.out.println("Original deck: " + deck);
        
        // Simulate cutting the deck at position 5
        Collections.rotate(deck, -5);
        System.out.println("After cut: " + deck);
        
        // Bring the top card to the middle
        Collections.rotate(deck, deck.size()/2);
        System.out.println("After middle rotation: " + deck);
    }
}

此示例使用旋转来模拟扑克牌操作。首先,我们通过向后旋转 5 个位置来“切”牌。然后,我们旋转牌堆的一半大小以将顶牌移到中间。

旋转是此类循环排列的理想选择。该示例展示了 Collections.rotate 如何模拟现实世界的旋转场景。

来源

Java Collections.rotate 文档

在本文中,我们深入探讨了 Java Collections.rotate 方法。我们涵盖了基本旋转、子列表旋转和实际应用。了解旋转对于许多列表操作任务很有价值。

作者

我的名字是 Jan Bodnar,我是一位经验丰富的程序员,在这一领域拥有多年的经验。我从 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。凭借超过 8 年的教学经验,我致力于分享我的知识并帮助其他人掌握编程概念。

列出所有Java教程