Перетасуйте список целых чисел с API-интерфейсом Java 8 Streams
Я попытался перевести следующую строку 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)
Как я могу перетасовать список с API-интерфейсом Java 8 Streams?
Ответы
Ответ 1
Здесь вы идете:
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]
Ответ 2
Вы можете найти следующий способ toShuffledList()
.
private static final Collector<?, ?, ?> SHUFFLER = Collectors.collectingAndThen(
Collectors.toList(),
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
Ответ 3
Вы можете использовать собственный компаратор, который "сортирует" значения по случайному значению:
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());
Преимущество этого решения состоит в том, что он интегрируется в потоковый конвейер.
Ответ 4
Чтобы выполнить перетасовку эффективно, вам нужны все значения заранее. Вы можете использовать Collections.shuffle() после преобразования потока в список, как в Scala.
Ответ 5
Это мое однострочное решение:
Я выбираю один случайный цвет:
colourRepository.findAll().stream().sorted((o1,o2)-> RandomUtils.nextInt(-1,1)).findFirst().get()