什麼是最有效的方式從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