Перетасуйте список целых чисел с API-интерфейсом Java 8 Streams

java scala java-stream

14377 просмотра

6 ответа

35909 Репутация автора

Я попытался перевести следующую строку Scala на Java 8 с помощью Streams API:

// Scala
util.Random.shuffle((1 to 24).toList)

Чтобы записать эквивалент в Java, я создал ряд целых чисел:

IntStream.range(1, 25)

Я подозревал, что нашел toListметод в потоковом API, но знаю IntStreamтолько странный метод:

collect(
  Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)

Как я могу перетасовать список с Java 8 Streams API?

Автор: deamon Источник Размещён: 18.11.2013 09:31

Ответы (6)


1 плюс

434384 Репутация автора

Чтобы эффективно выполнять перетасовку, вам нужны все значения заранее. Вы можете использовать Collections.shuffle () после преобразования потока в список, как в Scala.

Автор: Peter Lawrey Размещён: 18.11.2013 09:36

27 плюса

12402 Репутация автора

Решение

Ну вот:

List<Integer> integers =
    IntStream.range(1, 10)                      // <-- creates a stream of ints
        .boxed()                                // <-- converts them to Integers
        .collect(Collectors.toList());          // <-- collects the values to a list

Collections.shuffle(integers);

System.out.println(integers);

Печать:

[8, 1, 5, 3, 4, 2, 6, 9, 7]
Автор: Andrey Chaschev Размещён: 18.11.2013 09:39

5 плюса

1008 Репутация автора

Вы можете использовать собственный компаратор, который «сортирует» значения по случайному значению:

public final class RandomComparator<T> implements Comparator<T> {

    private final Map<T, Integer> map = new IdentityHashMap<>();
    private final Random random;

    public RandomComparator() {
        this(new Random());
    }

    public RandomComparator(Random random) {
        this.random = random;
    }

    @Override
    public int compare(T t1, T t2) {
        return Integer.compare(valueFor(t1), valueFor(t2));
    }

    private int valueFor(T t) {
        synchronized (map) {
            return map.computeIfAbsent(t, ignore -> random.nextInt());
        }
    }

}

Каждый объект в потоке (лениво) связывает случайное целочисленное значение, которое мы сортируем. Синхронизация на карте связана с параллельными потоками.

Затем вы можете использовать его так:

IntStream.rangeClosed(0, 24).boxed()
    .sorted(new RandomComparator<>())
    .collect(Collectors.toList());

Преимущество этого решения заключается в том, что он интегрируется в поточный конвейер.

Автор: Xavier Размещён: 07.03.2016 02:30

16 плюса

29171 Репутация автора

Вы можете найти следующий toShuffledList()способ полезный.

private static final Collector<?, ?, ?> SHUFFLER = Collectors.collectingAndThen(
        Collectors.toCollection(ArrayList::new),
        list -> {
            Collections.shuffle(list);
            return list;
        }
);

@SuppressWarnings("unchecked")
public static <T> Collector<T, ?, List<T>> toShuffledList() {
    return (Collector<T, ?, List<T>>) SHUFFLER;
}

Это позволяет использовать один из следующих типов:

IntStream.rangeClosed('A', 'Z')
         .mapToObj(a -> (char) a)
         .collect(toShuffledList())
         .forEach(System.out::print);

Пример вывода:

AVBFYXIMUDENOTHCRJKWGQZSPL
Автор: Paul Boddington Размещён: 03.04.2016 10:21

-2 плюса

917 Репутация автора

Это мое однострочное решение: я выбираю один случайный цвет:

colourRepository.findAll().stream().sorted((o1,o2)-> RandomUtils.nextInt(-1,1)).findFirst().get()
Автор: kozla13 Размещён: 15.01.2018 03:22

0 плюса

4564 Репутация автора

Если вы ищете «потоковое только» решение и детерминированный, просто «случайный» порядок по сравнению с «случайным» заказом, достаточно хорош, вы всегда можете сортировать свои значения intпо хеш-значению:

List<Integer> xs=IntStream.range(0, 10)
    .boxed()
    .sorted( (a, b) -> a.hashCode() - b.hashCode() )
    .collect(Collectors.toList());

Если вы предпочитаете использовать int[]a List<Integer>, вы можете просто удалить их после этого. К сожалению, вы прошли шаг по боксу, чтобы применить обычай Comparator, поэтому не исключена эта часть процесса.

List<Integer> ys=IntStream.range(0, 10)
    .boxed()
    .sorted( (a, b) -> a.hashCode() - b.hashCode() )
    .mapToInt( a -> a.intValue())
    .toArray();
Автор: sigpwned Размещён: 31.05.2018 04:08
Вопросы из категории :
32x32