public static <T> T random(Collection<T> coll) {
int num = (int) (Math.random() * coll.size());
for(T t: coll) if (--num < 0) return t;
throw new AssertionError();
}
public static <E> E getRandomElement(Collection<E> collection)
{
if(collection.isEmpty())
throw new IllegalArgumentException("Cannot return a random value from an empty collection!");
int randomIndex = ThreadLocalRandom.current().nextInt(collection.size());
if(collection instanceof RandomAccess)
return ((List<E>) collection).get(randomIndex);
for(E element : collection)
{
if(randomIndex == 0)
return element;
randomIndex--;
}
throw new IllegalStateException("How did we get here?"); //unreachable
}
public static <T> T getRandomElement(final Collection<T> collection) {
return Objects.requireNonNull(collection, "collection is null").stream()
.skip(ThreadLocalRandom.current().nextInt(Math.max(collection.size(), 1)))
.findFirst().orElseThrow(() -> new IllegalArgumentException("collection is empty"));
}
9条答案
按热度按时间km0tfn4u1#
使用Lambdas可以非常快速地完成此操作,并处理Collection为空的情况。
4szc88ey2#
最有效的方法是只迭代到你需要的程度。
4dbbbstv3#
tjvv9vkg4#
我知道这是一个旧的线程,但我很惊讶,没有人提到
RandomAccess
接口,这标志着List
实现具有非常快速的索引访问。以下是
RandomAccess
的文档:List实现使用的标记接口,用于指示它们支持快速(通常为恒定时间)随机访问。此接口的主要用途是允许泛型算法改变其行为,以便在应用于随机或顺序访问列表时提供良好的性能。
例如:它由
ArrayList
实现,与LinkedList
相反。这是我的解决方案,利用它:
jm2pwxwz5#
几个选项(按效率排序):
js5cn81o6#
如果您不介意第三方库,Utils库有一个IterableUtils,它有一个randomFrom(Iterable iterable)方法,该方法将接受一个Collection并从中返回一个随机元素
它位于Maven中央存储库中,网址为:
wnavrhmk7#
使用Google Guava
Iterables.get()
方法的解决方案:如果你也想处理空集合,可以使用带有
defaultValue
的方法:Iterables.get(from, i, null)
q9yhzks08#
可以将
Stream#skip
与ThreadLocalRandom
沿着使用。5fjcxozz9#
用户
Collections.shuffle(list);
。然后你可以只得到第一个元素。它将是随机的。或者你也可以这样做