什么是最有效的方式从Java8流api列表中获取随机元素?如何从流api的列表中获得一个随机元素?
Arrays.asList(new Obj1(), new Obj2(), new Obj3());
谢谢。
什么是最有效的方式从Java8流api列表中获取随机元素?如何从流api的列表中获得一个随机元素?
Arrays.asList(new Obj1(), new Obj2(), new Obj3());
谢谢。
为什么与流?你只需要从0得到一个随机数,以列表的大小,然后在这个指标叫get
:
Random r = new Random();
ElementType e = list.get(r.nextInt(list.size());
流会给你这里没有什么有趣的,但你可以尝试:
Random r = new Random();
ElementType e = list.stream().skip(r.nextInt(list.size()-1).findFirst().get();
想法是跳过任意数量的元素(但不是最后一个!),然后获取第一个元素(如果存在)。结果你将有一个Optional<ElementType
这将是非空的,然后提取其值get
。在跳过之后,您有很多选择。
这里使用流是非常低效的...
注意:这些解决方案都需要在考虑空单,但问题是在非空列表定义。
如果HAVE使用流,我写了一个优雅的,虽然非常低效的收集,没有工作:
/**
* Returns a random item from the stream (or null in case of an empty stream).
* This operation can't be lazy and is inefficient, and therefore shouldn't
* be used on streams with a large number or items or in performance critical sections.
* @return a random item from the stream or null if the stream is empty.
*/
public static <T> Collector<T, List<T>, T> randomItem() {
final Random RANDOM = new Random();
return Collector.of(() -> (List<T>) new ArrayList<T>(),
(acc, elem) -> acc.add(elem),
(list1, list2) -> ListUtils.union(list1, list2), // Using a 3rd party for list union, could be done "purely"
list -> list.isEmpty() ? null : list.get(RANDOM.nextInt(list.size())));
}
用法:
@Test
public void standardRandomTest() {
assertThat(Stream.of(1, 2, 3, 4).collect(randomItem())).isBetween(1, 4);
}
它将如果列表产生一个NoSuchElementException是空的 – Andrew
@AndrewTobilko好吧,但从空列表中提取一个随机元素总是未定义的。同样适合您的解决方案... –
@ Jean-BaptisteYunés有道理,谢谢。 – aekber