Java 从集合中获取随机元素
我有一个Java 从集合中获取随机元素,java,Java,我有一个集合如何从中随机获得一个Obj 我已经检查了,但似乎没有办法,因为迭代器是访问集合的唯一方法。我必须迭代它才能得到一个随机对象吗 UserCollections.shuffle(列表)。然后你就可以得到第一个元素。这将是随机的 或者你也可以这样做 int size = list.size(); int item = new Random().nextInt(size); list.get(item ) 几个选项(按效率顺序): 使用列表而不是集合 使用random.nextInt(
集合
如何从中随机获得一个Obj
我已经检查了,但似乎没有办法,因为迭代器是访问集合的唯一方法。我必须迭代它才能得到一个随机对象吗 User
Collections.shuffle(列表)代码>。然后你就可以得到第一个元素。这将是随机的
或者你也可以这样做
int size = list.size();
int item = new Random().nextInt(size);
list.get(item )
几个选项(按效率顺序):
- 使用列表而不是集合
- 使用random.nextInt(collection.size())生成随机索引,获取迭代器并进行迭代
- 使用random.nextInt(collection.size())生成随机索引,使用toArray()将集合转换为数组,并为该数组编制索引
最有效的方法是只根据需要进行迭代
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 T random(收集coll){
int num=(int)(Math.random()*coll.size());
对于(T T:coll),如果(--num<0)返回T;
抛出新的断言错误();
}
使用Lambdas,您可以非常快速地执行此操作,并在集合为空时处理此情况
public static <E> Optional<E> getRandom (Collection<E> e) {
return e.stream()
.skip((int) (e.size() * Math.random()))
.findFirst();
}
公共静态可选getRandom(集合e){
返回e.stream()
.skip((int)(例如size()*Math.random())
.findFirst();
}
如果您不介意使用第三方库,则该库具有randomFrom(Iterable Iterable)方法,该方法将获取集合并从中返回随机元素
Collection<Object> collection = ....;
Object random = IterableUtils.randomFrom(collection);
Collection=。。。。;
Object random=iterabluetils.randomFrom(集合);
它位于Maven中央存储库中,位于:
<dependency>
<groupId>com.github.rkumsher</groupId>
<artifactId>utils</artifactId>
<version>1.3</version>
</dependency>
com.github.rkumsher
乌提尔斯
1.3
使用谷歌番石榴法的解决方案:
private T getRandomObject(从中收集){
随机rnd=新随机();
int i=rnd.nextInt(from.size());
返回Iterables.get(from,i);
}
如果您还想处理空集合,可以使用:Iterables.get(from,i,null)
我知道这是一个旧线程,但是我很惊讶没有人提到RandomAccess
接口,它标志着列表
实现具有非常快速的索引访问
以下是RandomAccess的文档:
列表实现使用的标记接口,用于指示它们支持快速(通常为常数时间)随机访问。此接口的主要目的是允许通用算法在应用于随机或顺序访问列表时改变其行为,以提供良好的性能
例如:它是通过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
}
}
publicstatice getrandom元素(集合)
{
if(collection.isEmpty())
返回null;
int randomIndex=ThreadLocalRandom.current().nextInt(collection.size());
if(随机访问的收集实例)
{
列表=(列表)集合;
返回列表.get(随机索引);
}
其他的
{
for(E元素:集合)
{
if(randomIndex==0)
返回元素;
随机指数--;
}
返回null;//不可访问
}
}
可以与一起使用
publicstatict getrandom元素(最终集合){
return Objects.requirennull(集合,“集合为空”).stream()
.skip(ThreadLocalRandom.current().nextInt(Math.max(collection.size(),1)))
.findFirst().OrelsThrow(()->新的IllegalArgumentException(“集合为空”);
}
从集合的size()中获取一个随机整数,即,random.nextInt(collection.size())
,并迭代该次数。如果需要随机访问,则需要列表。这将永远不会返回集合中的最后一项。您应该使用rnd.nextInt(from.size())
。将整个集合放入一个数组中仅仅获取一个元素似乎有些浪费。@Keppil-这难道不意味着我们永远无法从集合中获取第一项吗?@Sridhar Sarnobat:No,nextInt(max)返回一个从0
到max-1
的值。你不能洗牌集合,因为它需要列表,这是OP要求的。喜欢这个答案,但对它做了一个小调整:skip(new Random().nextInt(Collection.size())
而不是skip((int)(e.size()*Math.Random())
private <T> T getRandomObject(Collection<T> from) {
Random rnd = new Random();
int i = rnd.nextInt(from.size());
return Iterables.get(from, i);
}
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
}
}
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"));
}