我有一个List,其中包含根据索引访问的元素。在这个列表中,我需要能够根据它们的索引“旋转”4个元素的组。例如,在列表中
[a, b, c, d, e ,f , g, h, i, j, k, l]
我想旋转c,f,i,l以获得
[a, b, l, d, e ,c , g, h, f, j, k, i]
你将如何实现这个?
答案 0 :(得分:6)
如果您只需要在List
的4个索引处旋转1个元素,您就可以编写一个简单的通用方法,如下所示:
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);
}
这会循环旋转任意List<T>
的4个元素。请记住List.set
返回之前在该索引处的元素,因此如果您愿意,可以以单行编写整个方法:
// one-liner version
list.set(i3, list.set(i2, list.set(i1, list.set(i0, list.get(i3)))));
使用此辅助方法,您将拥有:
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]
// * * * *
IF 你需要一种方法来旋转任意数量的元素任意距离,然后你可以创建另一个List
的实时视图,并且然后你可以Collections.rotate
查看。
IF 元素是连续的,例如,您只需使用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]
// * * * * *
由于元素不是连续的,因此您无法使用subList
,但您可以编写例如PeriodicalLiveViewList
课程。你希望能够写出这样的东西:
System.out.println(PeriodicalLiveViewList.of(list, 3, 2));
// [c, f, i, l]
Collections.rotate(PeriodicalLiveViewList.of(list, 3, 2), 1);
基本上你创建另一个List
,其元素是另一个List
的第3个元素,从索引2开始,作为实时视图。
如果您使用的是番石榴,可以使用ForwardingList
构建。如有必要,您也可以从头开始实现decorator pattern。
答案 1 :(得分:2)
这就是我想出的。这是一个相当简单的蛮力解决方案,但它是可扩展的。
import java.util.Arrays;
import java.util.List;
public class ArrayRotator {
public static void main(String... args) {
List<String> target = Arrays.asList("a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l");
System.out.println(target);
target = rotate(target, 3);
System.out.println(target);
}
private static List<String> rotate(List<String> aList, int anOffset) {
String[] result = new String[aList.size()];
for (int i = 0; i < aList.size(); i++) {
if (0 == (i + 1) % anOffset) {
if (aList.size() > (i + anOffset)) {
result[i + anOffset ] = aList.get(i);
} else {
result[anOffset - 1] = aList.get(i);
}
} else {
result[i] = aList.get(i);
}
}
return Arrays.asList(result);
}
}
这是我得到的输出:
[a, b, c, d, e, f, g, h, i, j, k, l]
[a, b, l, d, e, c, g, h, f, j, k, i]
在这种情况下,我没有考虑Collections
功能,因为它似乎比这更复杂。我不确定哪种算法在大型列表上更有效。也许您可以将功能组合如下:
import java.util.List;
public class ListRotator {
public static void main(String... args) {
List<String> target = Arrays.asList("a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l");
System.out.println(target);
rotate(target, 3);
System.out.println(target);
}
private static void rotate(List<String> aList, int anOffset) {
for (int i = anOffset-1; i < aList.size()-anOffset; i += anOffset) {
Collections.rotate(aList.subList(i, i+anOffset), -1);
}
Collections.rotate(aList.subList(anOffset-1, aList.size()), 1);
}
}
它生成与上面相同的输出。