首页 > 解决方案 > IntStream 的随机排列

问题描述

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

for (int i = 0; i < max; i++) {
    // do stuff with i
}

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
}

这既不高效也不优雅。是否可以在某个范围内创建一个Stream(理想情况下是一个),但它是否返回其元素被打乱?IntStream我正在考虑以下内容:

IntStream.range(0, max)
        .shuffled() // this method doesn't exist
        .forEach(IntConsumer::accept);

结果IntStream仍应仅包含该范围内的所有[0, max)元素一次


这不是这个问题的重复,因为我不想创建一个List并随机播放它。该解决方案具有巨大的开销,因为它与Integers 一起工作,同时还冗余地创建和改组 a List。我在自己的示例中提供了该解决方案,因此我完全了解这种方法。

标签: javajava-stream

解决方案


这个怎么样?它与您拥有的几乎相同,只是它封装了所有细节,并为您提供了一个纯粹的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;
    }
}

推荐阅读