Выберите случайное значение из перечисления?
Если у меня есть перечисление, как это:
public enum Letter {
A,
B,
C,
//...
}
что является лучшим способом, чтобы выбрать один случайным образом? Это не должно быть пуленепробиваемым качеством производства, но довольно равномерное распределение было бы неплохо.
я мог бы сделать что-то подобное
private Letter randomLetter() {
int pick = new Random().nextInt(Letter.values().length);
return Letter.values()[pick];
}
но есть ли лучший способ? Я чувствую, что это то, что было раньше.
12 ответов:
единственное, что я хотел бы предложить, это кэширование результата
values()потому что каждый вызов копирует массив. Кроме того, не создано!--2--> каждый раз. Держи одну. Кроме того, то, что вы делаете, прекрасно. Итак: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)); } }
один способ все, что вам нужно для всех ваших случайных перечислений:
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();
объединение предложений Клетус и Гелиоса,
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<E>> { 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)]; } } }Edit: Ой, я забыл параметр ограниченного типа,
<E extends Enum<E>>.
согласен с Stphen C & helios. Лучший способ получить случайный элемент из перечисления:
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)]; } }
Если вы делаете это для тестирования вы можете использовать быстрая проверка (это 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 работает с вариант развития событий.
вероятно, проще всего иметь функцию для выбора случайного значения из массива. Это более общий, и его легко вызвать.
<T> T randomValue(T[] values) { return values[mRandom.nextInt(values.length)]; }вызовы так:
MyEnum value = randomValue(MyEnum.values());
здесь версия, которая использует перемешивание и потоки
List<Direction> letters = Arrays.asList(Direction.values()); Collections.shuffle(letters); return letters.stream().findFirst().get();
это, вероятно, самый краткий способ достижения вашей цели.Все, что вам нужно сделать, это позвонить
Letter.getRandom()и вы получите случайное перечисление букв.public enum Letter { A, B, C, //... public static Letter getRandom() { return values()[(int) (Math.random() * values().length)]; } }
его 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(); }
Я бы использовал это:
private static Random random = new Random(); public Object getRandomFromEnum(Class<? extends Enum<?>> clazz) { return clazz.values()[random.nextInt(clazz.values().length)]; }
Comments