Это быстрее, чем цикл for-each в принятом ответе:
int index = rand.nextInt(set.size());
Iterator<Object> iter = set.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
Конструкция for-each вызывает Iterator.hasNext()
в каждом цикле, но с index < set.size()
эта проверка не требует дополнительных затрат. Я видел увеличение скорости на 10-20%, но YMMV. (Кроме того, это компилируется без добавления дополнительного оператора возврата.)
Обратите внимание, что этот код (и большинство других ответов) может быть применен к любой коллекции, а не только к множеству. В общей форме метода:
public static <E> E choice(Collection<? extends E> coll, Random rand) {
if (coll.size() == 0) {
return null; // or throw IAE, if you prefer
}
int index = rand.nextInt(coll.size());
if (coll instanceof List) { // optimization
return ((List<? extends E>) coll).get(index);
} else {
Iterator<? extends E> iter = coll.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
}
}