我不时地发现自己有索引循环,我想要将顺序置换为一些随机顺序.我通常会从类似的东西过渡
for (int i = 0; i < max; i++) {
// do stuff with i
}
Run Code Online (Sandbox Code Playgroud)
至
List<Integer> indices = IntStream.range(0, max)
.boxed()
toCollection(() -> new ArrayList(max)));
Collections.shuffle(indices);
for (int i = 0; i < max; i++) {
int index = indices.get(i);
// do stuff with index
}
Run Code Online (Sandbox Code Playgroud)
这既不高效也不优雅.是否有可能在某个范围内创建一个Stream
(理想情况下IntStream
),但让它返回其元素?我正在考虑以下方面的事情:
IntStream.range(0, max)
.shuffled() // this method doesn't exist
.forEach(IntConsumer::accept);
Run Code Online (Sandbox Code Playgroud)
结果IntStream
应该仍然包括该范围内的所有元素[0, max)
恰好一次.
这不是这个问题的重复,因为我不想创建List
和改变它.这个解决方案有很大的开销,因为它使用Integer
s,同时还冗余地创建和改组List
.我在我自己的例子中提供了这个解决方案,所以我完全了解这种方法.
这个怎么样?它与你拥有的几乎完全相同,只是它封装了所有细节,只是给你一个纯净的IntStream
.此外,它不需要做太多拳击和拆箱.
public class ShuffledIntStream {
public static IntStream to(int max) {
Random r = new Random();
int[] values = new int[max];
for (int i = 0; i < max; i++) {
values[i] = i;
}
for (int i = max; i > 1; i--) {
swap(values, i - 1, r.nextInt(max));
}
return IntStream.of(values);
}
private static void swap(int[] values, int i, int j) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
Run Code Online (Sandbox Code Playgroud)