Как выбрать случайный элемент из набора? Я особенно заинтересован в выборе случайного элемента из HashSet или LinkedHashSet в Java. Решения для других языков также приветствуются.
В Java 8:
static <E> E getRandomSetElement(Set<E> set) { return set.stream().skip(new Random().nextInt(set.size())).findFirst().orElse(null); }
Поскольку вы сказали "Решения для других языков также приветствуются", вот версия для Python:
>>> import random >>> random.choice([1,2,3,4,5,6]) 3 >>> random.choice([1,2,3,4,5,6]) 4
Это идентично принятому ответу (Хот), но с удаленными ненужными переменными size и i.
size
i
int random = new Random().nextInt(myhashSet.size()); for(Object obj : myhashSet) { if (random-- == 0) { return obj; } }
Несмотря на то, что покончено с двумя вышеупомянутыми переменными, вышеупомянутое решение все еще остается случайным, потому что мы полагаемся на случайное (начиная со случайно выбранного индекса) уменьшение в сторону 0 на каждой итерации.
0
после прочтения этой темы, лучшее, что я мог написать:
static Random random = new Random(System.currentTimeMillis()); public static <T> T randomChoice(T[] choices) { int index = random.nextInt(choices.length); return choices[index]; }
Если вы не возражаете против сторонней библиотеки, библиотека Utils имеет IterableUtils , который имеет метод randomFrom (Iterable iterable), который примет Set и вернет случайное элемент из него
Set<Object> set = new HashSet<>(); set.add(...); ... Object random = IterableUtils.randomFrom(set);
Он находится в Центральном репозитории Maven по адресу:
<dependency> <groupId>com.github.rkumsher</groupId> <artifactId>utils</artifactId> <version>1.3</version> </dependency>
С Гуавой мы можем сделать немного лучше, чем ответ Кот:
public static E random(Set<E> set) { int index = random.nextInt(set.size(); if (set instanceof ImmutableSet) { // ImmutableSet.asList() is O(1), as is .get() on the returned list return set.asList().get(index); } return Iterables.get(set, index); }
Если установленный размер не большой, то с помощью массивов это можно сделать.
int random; HashSet someSet; <Type>[] randData; random = new Random(System.currentTimeMillis).nextInt(someSet.size()); randData = someSet.toArray(); <Type> sResult = randData[random];
Общее решение, использующее ответ Хота в качестве отправной точки.
/** * @param set a Set in which to look for a random element * @param <T> generic type of the Set elements * @return a random element in the Set or null if the set is empty */ public <T> T randomElement(Set<T> set) { int size = set.size(); int item = random.nextInt(size); int i = 0; for (T obj : set) { if (i == item) { return obj; } i++; } return null; }
Самый простой в Java 8:
outbound.stream().skip(n % outbound.size()).findFirst().get()
где n - случайное целое число. Конечно, он имеет меньшую производительность, чем у for(elem: Col)
n
for(elem: Col)
Если вы действительно хотите выбрать «любой» объект из Set, без каких-либо гарантий случайности, проще всего взять первое, возвращенное итератором.
Set
Set<Integer> s = ... Iterator<Integer> it = s.iterator(); if(it.hasNext()){ Integer i = it.next(); // i is a "random" object from set }