Java: выберите случайное значение из перечисления?
Если у меня есть перечисление вроде этого:
public enum Letter {
A,
B,
C,
//...
}
Каков наилучший способ выбрать один случайным образом? Это не обязательно должно быть качество продукции пуленепробиваемое, но довольно ровное распределение было бы приятным.
Я мог бы сделать что-то вроде этого
private Letter randomLetter() {
int pick = new Random().nextInt(Letter.values().length);
return Letter.values()[pick];
}
Но есть ли лучший способ? Я чувствую, что это то, что было решено раньше.
Ответы
Ответ 1
Единственное, что я хотел бы предложить, - это кэшировать результат values()
, потому что каждый вызов копирует массив. Кроме того, не создавайте Random
каждый раз. Держи один. Кроме того, что вы делаете, все в порядке. Итак:
public enum Letter {
A,
B,
C,
//...
private static final List<Letter> VALUES =
Collections.unmodifiableList(Arrays.asList(values()));
private static final int SIZE = VALUES.size();
private static final Random RANDOM = new Random();
public static Letter randomLetter() {
return VALUES.get(RANDOM.nextInt(SIZE));
}
}
Ответ 2
Единственный метод - это все, что вам нужно для всех ваших случайных перечислений:
public static <T extends Enum<?>> T randomEnum(Class<T> clazz){
int x = random.nextInt(clazz.getEnumConstants().length);
return clazz.getEnumConstants()[x];
}
Что вы будете использовать:
randomEnum(MyEnum.class);
Я также предпочитаю использовать SecureRandom как:
private static final SecureRandom random = new SecureRandom();
Ответ 3
Объединив предложения cletus и helios,
import java.util.Random;
public class EnumTest {
private enum Season { WINTER, SPRING, SUMMER, FALL }
private static final RandomEnum<Season> r =
new RandomEnum<Season>(Season.class);
public static void main(String[] args) {
System.out.println(r.random());
}
private static class RandomEnum<E extends Enum> {
private static final Random RND = new Random();
private final E[] values;
public RandomEnum(Class<E> token) {
values = token.getEnumConstants();
}
public E random() {
return values[RND.nextInt(values.length)];
}
}
}
Изменить: Ой, я забыл параметр ограниченного типа, <E extends Enum>
.
Ответ 4
Одиночная строка
return Letter.values()[new Random().nextInt(Letter.values().length)];
Ответ 5
Согласитесь с Stphen C и helios. Лучший способ получить случайный элемент из Enum:
public enum Letter {
A,
B,
C,
//...
private static final Letter[] VALUES = values();
private static final int SIZE = VALUES.length;
private static final Random RANDOM = new Random();
public static Letter getRandomLetter() {
return VALUES[RANDOM.nextInt(SIZE)];
}
}
Ответ 6
Letter lettre = Letter.values()[(int)(Math.random()*Letter.values().length)];
Ответ 7
Если вы сделаете это для тестирования, вы можете использовать Quickcheck (это порт Java, над которым я работал).
import static net.java.quickcheck.generator.PrimitiveGeneratorSamples.*;
TimeUnit anyEnumValue = anyEnumValue(TimeUnit.class); //one value
Он поддерживает все примитивные типы, тип композиции, коллекции, различные функции распределения, границы и т.д. Он поддерживает бегунов, выполняющих несколько значений:
import static net.java.quickcheck.generator.PrimitiveGeneratorsIterables.*;
for(TimeUnit timeUnit : someEnumValues(TimeUnit.class)){
//..test multiple values
}
Преимущество Quickcheck заключается в том, что вы можете определять тесты на основе спецификации где простой TDD работает со сценариями.
Ответ 8
Вероятно, проще всего иметь функцию для выбора случайного значения из массива. Это более общее и простое вызов.
<T> T randomValue(T[] values) {
return values[mRandom.nextInt(values.length)];
}
Вызываем так:
MyEnum value = randomValue(MyEnum.values());
Ответ 9
Это eaiser для реализации случайной функции на перечислении.
public enum Via {
A, B;
public static Via viaAleatoria(){
Via[] vias = Via.values();
Random generator = new Random();
return vias[generator.nextInt(vias.length)];
}
}
а затем вы вызываете его из класса, который вам нужен, как это
public class Guardia{
private Via viaActiva;
public Guardia(){
viaActiva = Via.viaAleatoria();
}
Ответ 10
Здесь версия, в которой используются тасование и потоки
List<Direction> letters = Arrays.asList(Direction.values());
Collections.shuffle(letters);
return letters.stream().findFirst().get();
Ответ 11
Это, вероятно, самый сжатый способ достижения вашей цели. Все, что вам нужно сделать, это позвонить Letter.getRandom()
, и вы получите случайное письмо с перечислением.
public enum Letter {
A,
B,
C,
//...
public static Letter getRandom() {
return values()[(int) (Math.random() * values().length)];
}
}
Ответ 12
Я бы использовал это:
private static Random random = new Random();
public Object getRandomFromEnum(Class<? extends Enum<?>> clazz) {
return clazz.values()[random.nextInt(clazz.values().length)];
}