使用Java 8 Streams API对整数列表进行随机播放
我尝试使用Streams API将以下Scala行转换为Java 8:
// Scala util.Random.shuffle((1 to 24).toList)
要在Java中编写等效项,我创建了一系列整数:
IntStream.range(1, 25)
我怀疑在流API中找到了一个toList
方法,但是IntStream
只知道奇怪的方法:
collect( Supplier supplier, ObjIntConsumer accumulator, BiConsumer combiner)
如何使用Java 8 Streams API对列表进行混洗?
干得好:
List 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]
您可能会发现以下toShuffledList()
方法很有用。
private static final Collector, ?, ?> SHUFFLER = Collectors.collectingAndThen( Collectors.toList(), list -> { Collections.shuffle(list); return list; } ); @SuppressWarnings("unchecked") public static Collector> toShuffledList() { return (Collector>) SHUFFLER; }
这使得以下类型的单线:
IntStream.rangeClosed('A', 'Z') .mapToObj(a -> (char) a) .collect(toShuffledList()) .forEach(System.out::print);
输出示例:
AVBFYXIMUDENOTHCRJKWGQZSPL
您可以使用自定义比较器按随机值“排序”值:
public final class RandomComparator implements Comparator { private final Map 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());
该解决方案的优点是它集成在流管道中。
要有效地执行shuffle,您需要提前获取所有值。 将流转换为类似于Scala中的列表后,可以使用Collections.shuffle()。
如果你正在寻找一个“仅限流媒体”的解决方案和一个确定性的解决方案,只需“偶然”排序而不是“随机”排序就足够了,你总是可以用一个哈希值对你的int
排序:
List xs=IntStream.range(0, 10) .boxed() .sorted( (a, b) -> a.hashCode() - b.hashCode() ) .collect(Collectors.toList());
如果您想要一个int[]
不是List
,那么您可以在之后将它们取消装箱。 不幸的是,你已经通过拳击步骤来应用自定义Comparator
,所以没有消除这部分过程。
List ys=IntStream.range(0, 10) .boxed() .sorted( (a, b) -> a.hashCode() - b.hashCode() ) .mapToInt( a -> a.intValue()) .toArray();
这是我的一线解决方案:我选择一种随机颜色:
colourRepository.findAll().stream().sorted((o1,o2)-> RandomUtils.nextInt(-1,1)).findFirst().get()