Случайная перестановка IntStream - PullRequest
0 голосов
/ 19 февраля 2019

Время от времени я оказываюсь с индексированными циклами, для которых я хочу переставить порядок в некоторый случайный порядок.Я обычно перехожу из чего-то вроде

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 и перемешивать его.Это решение имеет значительные накладные расходы, поскольку оно работает с Integer s, а также создает и перетасовывает List с избыточностью.Я представил это решение в своем собственном примере, поэтому я полностью осознаю этот подход.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Как насчет этого?Это почти то же самое, что и у вас, за исключением того, что она заключает в себе все мелкие частицы и просто дает вам чистую 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;
    }
}
0 голосов
/ 19 февраля 2019

Вы можете использовать Random.ints:

new Random().ints(0, max)
    .distinct()
    .limit(max)
    .forEach(IntConsumer::accept);

ints создаст поток в диапазоне от 0 до max, distinct следит за тем, чтобы дубликатов не было, и limit, чтобы получить ровно столько, сколько вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...