我有一个带有值元素的列表整数: 0,7,2,1,6,5。
我知道我可以使用方法
Collections.shuffle(list);
洗牌我的名单。但我不想改变第二名的价值。应始终为7.
我该怎么做?
答案 0 :(得分:9)
您可以随机播放Collection,然后将7恢复到第二个位置:
Collections.shuffle(list);
list.set(list.indexOf(7),list.get(2));
list.set(2,7);
或更短:
Collections.shuffle(list);
Collections.swap(list, 2, list.indexOf(7));
正如其他人所建议的那样,您也可以在改组之前删除要保留其位置的元素,然后将其添加到同一位置。
对于ArrayLists,这两种方式应该花费相似的时间(在最坏的情况下是线性的),因为在我的回答indexOf
中需要线性时间,但在替代解决方案中删除并添加元素(特别是如果索引关闭)到列表的开头)将花费ArrayList
的线性时间,因为删除/添加索引之后的所有元素都必须被推送到新索引。
答案 1 :(得分:6)
轻松防止移动任意数量的元素
答案 2 :(得分:2)
有一个替代解决方案,它可以更长,但对于长列表来说可能更快:
public static <T> void shuffleExcept(final List<T> list, final int position) {
List<T> view = new AbstractList<T>() {
@Override
public T get(int index) {
return list.get(index >= position ? index+1 : index);
}
@Override
public T set(int index, T element) {
return list.set(index >= position ? index+1 : index, element);
}
@Override
public int size() {
return list.size()-1;
}
};
Collections.shuffle(view);
}
在这里,我们创建一个&#34;视图&#34;除了我们想要保留的元素之外的整个列表的原始列表(我们只是移动后续元素的索引)。接下来我们改变这种观点。这就是界面之美:你可以要求现有的方法做一些与传递新界面实现不同的东西。
用法示例:
List<Integer> input = Arrays.asList(0, 7, 2, 1, 6, 5);
shuffleExcept(input, 1);
System.out.println(input);
shuffleExcept(input, 1);
System.out.println(input);
shuffleExcept(input, 1);
System.out.println(input);
shuffleExcept(input, 1);
System.out.println(input);
shuffleExcept(input, 1);
System.out.println(input);
shuffleExcept(input, 1);
System.out.println(input);
shuffleExcept(input, 1);
System.out.println(input);
典型输出:
[6, 7, 5, 2, 1, 0]
[5, 7, 6, 1, 2, 0]
[6, 7, 2, 0, 5, 1]
[6, 7, 2, 0, 5, 1]
[2, 7, 0, 5, 6, 1]
[6, 7, 0, 2, 5, 1]
[5, 7, 2, 0, 1, 6]