IntStream的随机排列

Neu*_*ron 5 java java-stream

我不时地发现自己有索引循环,我想要将顺序置换为一些随机顺序.我通常会从类似的东西过渡

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和改变它.这个解决方案有很大的开销,因为它使用Integers,同时还冗余地创建和改组List.我在我自己的例子中提供了这个解决方案,所以我完全了解这种方法.

Wil*_*urn 5

这个怎么样?它与你拥有的几乎完全相同,只是它封装了所有细节,只是给你一个纯净的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)