1. 概述

Java为我们提供了多种方法来重新排列ArrayList中的元素。在这篇教程中,我们将探讨其中的三种。

2. 移动项目

最直接且可控的方法是直接将一个项目移动到新的位置。我们可以通过首先使用ArrayList.remove()方法,它会返回被移除的项目,然后使用ArrayList.add()在我们选择的位置重新插入该项目:

@Test
void givenAList_whenManuallyReordering_thenOneItemMovesPosition() {
    ArrayList<String> arrayList = new ArrayList<>(Arrays.asList("one", "two", "three", "four", "five"));

    String removed = arrayList.remove(3);
    arrayList.add(2, removed);

    ArrayList<String> expectedResult = new ArrayList<>(Arrays.asList("one", "two", "four", "three", "five"));
    assertEquals(expectedResult, arrayList);
}

在内部,ArrayList使用数组实现。这意味着移除和插入项目需要将其他所有项目都移动,这会产生较大的开销。因此,我们应该尽量避免这种方法,并使用下面两种方法之一,它们都能保持ArrayList的原始长度。

3. 交换两个项目

我们可以使用Collections.swap()方法来交换ArrayList中两个项目的顺序。swap()方法接受三个参数:首先是要调整的ArrayList,然后是两个要交换位置的项目的索引:

@Test
public void givenAList_whenUsingSwap_thenItemsSwapPositions() {
    ArrayList<String> arrayList = new ArrayList<>(Arrays.asList("one", "two", "three", "four", "five"));

    Collections.swap(arrayList, 1, 3);

    ArrayList<String> expectedResult = new ArrayList<>(Arrays.asList("one", "four", "three", "two", "five"));
    assertEquals(expectedResult, arrayList);
}

这里我们交换了索引为1和3的项目,并确认列表看起来符合预期。

4. 旋转整个列表

最后,我们还可以对列表应用旋转操作,将所有元素按照给定的距离进行位移。距离没有限制,如果我们想,可以多次循环。正向距离会使项目向右或向下(根据我们的视角)移动:

@Test
void givenAList_whenUsingRotateWithPositiveDistance_thenItemsMoveToTheRight() {
    ArrayList<String> arrayList = new ArrayList<>(Arrays.asList("one", "two", "three", "four", "five"));

    Collections.rotate(arrayList, 2);

    ArrayList<String> expectedResult = new ArrayList<>(Arrays.asList("four", "five", "one", "two", "three"));
    assertEquals(expectedResult, arrayList);
}

在这里,所有项目向右移动了两个位置,当到达末尾时又回到了开头。如果需要,我们也可以通过负向距离进行左旋转:

@Test
void givenAList_whenUsingRotateWithNegativeDistance_thenItemsMoveToTheLeft() {
    ArrayList<String> arrayList = new ArrayList<>(Arrays.asList("one", "two", "three", "four", "five"));

    Collections.rotate(arrayList, -2);

    ArrayList<String> expectedResult = new ArrayList<>(Arrays.asList("three", "four", "five", "one", "two"));
    assertEquals(expectedResult, arrayList);
}

5. 总结

在这篇文章中,我们了解了Java为我们重新排列ArrayList提供的三种选项。出于性能考虑,我们应该优先使用swap()rotate()。如果需要更多控制或者只有一个项目需要移动,我们已经学习了如何使用remove()add()方法手动将项目移到所需的位置。

如往常一样,示例代码的完整版本可以在GitHub上找到。