2017-08-31 75 views

回答

7

为什么与流?你只需要从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。在跳过之后,您有很多选择。

这里使用流是非常低效的...

注意:这些解决方案都需要在考虑空单,但问题是在非空列表定义。

+0

它将如果列表产生一个NoSuchElementException是空的 – Andrew

+0

@AndrewTobilko好吧,但从空列表中提取一个随机元素总是未定义的。同样适合您的解决方案... –

+0

@ Jean-BaptisteYunés有道理,谢谢。 – aekber

3

如果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); 
} 
相关问题