Перейти к содержанию

Генерация случайного значения из Enum

Из этой статьи узнаем, как сгенерировать случайное значение из enum.

Случайное значение Enum с помощью статического метода

Создадим статическую функцию, которая возвращает случайно сгенерированное значение из определенного набора enum. Значения Enum представляют собой набор констант; тем не менее, можно объявлять статические методы в теле класса enum. Будем использовать статический метод в качестве помощника для генерации случайного значения enum.

Объявляем метод внутри тела класса enum, который является статическим и возвращает значение enum. Этот метод вызовет nextInt() из объекта Random, назовем его randomDirection():

public enum Direction {
    EAST, WEST, SOUTH, NORTH;
    private static final Random PRNG = new Random();
    public static Direction randomDirection()  {
        Direction[] directions = values();
        return directions[PRNG.nextInt(directions.length)];
    }
}

Внутри randomDirection() вызываем метод nextInt() с целочисленным аргументом. Метод nextInt() возвращает случайное число для доступа к массиву directions; поэтому нужно убедиться, что целое число не выходит за пределы массива, передав связанный аргумент в nextInt(). Связанный аргумент – это общее количество направлений, которое не превысит размер массива. Кроме того, метод values() создает копию значений перечисления каждый раз, когда вызывается метод randomDirection(). Можно улучшить производительность, создав final список переменных-членов, к которому обращаемся после создания случайного индекса:

private static final Direction[] directions = values();

Теперь метод randomDirection() будет выглядеть следующим образом:

public static Direction randomDirection() { 
    return directions[PRNG.nextInt(directions.length)]; 
}

Наконец, мы можем сгенерировать случайное направление, вызвав метод:

Direction direction = Direction.randomDirection();

Случайное значение Enum с помощью дженериков

Можно использовать дженерики для генерации случайного значения enum. Используя дженерики, создаем класс, который принимает любой тип данных enum для генерации случайного значения:

public class RandomEnumGenerator<T extends Enum<T>> {
    private static final Random PRNG = new Random();
    private final T[] values;

    public RandomEnumGenerator(Class<T> e) {
        values = e.getEnumConstants();
    }

    public T randomEnum() {
        return values[PRNG.nextInt(values.length)];
    }
}

Обратите внимание, как метод randomEnum() напоминает метод randomDirection() из предыдущего примера. Разница в том, что класс RandomEnumGenerator имеет конструктор, который ожидает тип enum, из которого можно получить постоянные значения. Можно сгенерировать случайное направление, используя класс RandomEnumGenerator следующим образом:

RandomEnumGenerator reg = new RandomEnumGenerator(Direction.class);
Direction direction = (Direction) reg.randomEnum();

Здесь используем класс перечисления Direction из предыдущего раздела. RandomEnumGenerator принимает этот класс, и объект direction будет ссылаться на одно из постоянных значений класса Direction.

Заключение

Из данной статьи мы узнали, как получить случайное значение из enum. Мы рассмотрели два способа: использовать статический метод внутри класса enum, который генерирует случайное значение, строго ограниченное классом enum, в котором объявлен метод. Кроме того, мы увидели, как можно повысить производительность за счет кэширования постоянных значений. Наконец, мы воспользовались дженериками, используя класс, который принимает любой тип перечисления, чтобы получить случайное значение.

Полные примеры кода для этой статьи можно найти на GitHub.

Оригинал