如何旋转列表中的非连续元素

Man*_*lva 2 java

我有一个List包含根据其索引访问的元素.在这个列表中,我需要能够根据它们的索引"旋转"4个元素的组.例如在列表中

[a, b, c, d, e ,f , g, h, i, j, k, l]
Run Code Online (Sandbox Code Playgroud)

我想旋转c,f,i,l以获得

[a, b, l, d, e ,c , g, h, f, j, k, i]
Run Code Online (Sandbox Code Playgroud)

你将如何实现这个?

pol*_*nts 6

一个简单的解决方案

如果你只需要在a的4个索引处旋转1个元素List,你就可以编写一个简单的泛型方法,如下所示:

static <T> void rotate4(List<T> list, int i0, int i1, int i2, int i3) {
    T item = list.get(i3);
    item = list.set(i0, item);
    item = list.set(i1, item);
    item = list.set(i2, item);
    item = list.set(i3, item);
}
Run Code Online (Sandbox Code Playgroud)

这将循环旋转任何4个元素List<T>.请记住,List.set返回之前在该索引处的元素,因此如果需要,可以在一行中编写整个方法:

    // one-liner version
    list.set(i3, list.set(i2, list.set(i1, list.set(i0, list.get(i3)))));
Run Code Online (Sandbox Code Playgroud)

使用此辅助方法,您将拥有:

    List<Character> list = Arrays.asList(
        'a','b','c','d','e','f','g','h','i','j','k','l'
    );

    System.out.println(list);
    // [a, b, c, d, e, f, g, h, i, j, k, l]
    //        *        *        *        *

    rotate4(list, 2, 5, 8, 11);

    System.out.println(list);       
    // [a, b, l, d, e, c, g, h, f, j, k, i]
    //        *        *        *        *
Run Code Online (Sandbox Code Playgroud)

更通用的解决方案

如果您需要一种方法来旋转任意数量的元素任意距离,那么您可以创建另一个的实时视图List,然后您可以Collections.rotate查看该视图.

例如,如果元素是连续的,您只需使用subList:

    List<Character> list = Arrays.asList(
        'a','b','c','d','e','f','g','h','i','j','k','l'
    );

    System.out.println(list);
    // [a, b, c, d, e, f, g, h, i, j, k, l]
    //     *  *  *  *  *

    System.out.println(list.subList(1, 6));
    // [b, c, d, e, f]

    Collections.rotate(list.subList(1, 6), -2);
    System.out.println(list);
    // [a, d, e, f, b, c, g, h, i, j, k, l]
    //     *  *  *  *  *
Run Code Online (Sandbox Code Playgroud)

由于元素不是连续的,你不能使用subList,但你可以写例如PeriodicalLiveViewList类.你希望能够写出这样的东西:

    System.out.println(PeriodicalLiveViewList.of(list, 3, 2));
    // [c, f, i, l]

    Collections.rotate(PeriodicalLiveViewList.of(list, 3, 2), 1);
Run Code Online (Sandbox Code Playgroud)

基本上你创建了另一个List元素,它的元素是另一个元素List,从索引2开始,作为实时视图.

如果您使用的是番石榴,那么ForwardingList您可以使用它.如有必要,您也可以从头开始实现装饰器模式.

相关问题