我有Collection<Obj>
如何从中获取随机Obj
?
我检查了docs并且似乎没有办法,因为迭代器是访问集合的唯一方法。我是否必须迭代它以获得随机对象!?
答案 0 :(得分:23)
最有效的只能根据需要进行迭代。
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();
}
答案 1 :(得分:23)
使用Lambdas,您可以非常快速地执行此操作,并在Collection为空时处理案例。
public static <E> Optional<E> getRandom (Collection<E> e) {
return e.stream()
.skip((int) (e.size() * Math.random()))
.findFirst();
}
答案 2 :(得分:6)
private Object getRandomObject(Collection from) {
Random rnd = new Random();
int i = rnd.nextInt(from.size());
return from.toArray()[i];
}
答案 3 :(得分:1)
几种选择(按效率顺序):
答案 4 :(得分:1)
我知道这是一个旧线程,但是令我惊讶的是,没有人提到RandomAccess
接口,该接口没有方法,并且标记为List
实现的索引访问非常快。
这是RandomAccess
的文档:
List实现使用的Marker接口表示它们支持快速(通常为恒定时间)随机访问。此接口的主要目的是允许通用算法更改其行为,以便在应用于随机或顺序访问列表时提供良好的性能。
它是由ArrayList
实现的,而不是由LinkedList
实现的。
这是我利用它的解决方案:
public static <E> E getRandomElement(Collection<E> collection)
{
if(collection.isEmpty())
{
return null;
}
int randomIndex = ThreadLocalRandom.current().nextInt(collection.size());
if(collection instanceof RandomAccess)
{
List<E> list = (List<E>) collection;
return list.get(randomIndex);
}
else
{
for(E element : collection)
{
if(randomIndex == 0)
{
return element;
}
randomIndex--;
}
return null; //unreachable
}
}
答案 5 :(得分:0)
如果您不介意第三方库,documentation库的Utils具有randomFrom(Iterable iterable)方法,该方法将采用Collection并从中返回一个随机元素< / p>
<dependency>
<groupId>com.github.rkumsher</groupId>
<artifactId>utils</artifactId>
<version>1.3</version>
</dependency>
它位于Maven Central Repository:
<select multiple>
答案 6 :(得分:0)
使用Google Guava Iterables.get()
方法的解决方案:
private <T> T getRandomObject(Collection<T> from) {
Random rnd = new Random();
int i = rnd.nextInt(from.size());
return Iterables.get(from, i);
}
如果您还想处理空集合,则可以使用method with defaultValue
:Iterables.get(from, i, null)
答案 7 :(得分:0)
可以将 Stream#skip
与 ThreadLocalRandom
一起使用。
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"));
}
答案 8 :(得分:-4)
用户Collections.shuffle(list);
。然后你就可以得到第一个元素。这将是随机的。
或者您也可以这样做
int size = list.size();
int item = new Random().nextInt(size);
list.get(item )