Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pick a random value from an enum?

Tags:

java

enums

random

The only thing I would suggest is caching the result of values() because each call copies an array. Also, don't create a Random every time. Keep one. Other than that what you're doing is fine. So:

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));
  }
}

A single method is all you need for all your random enums:

    public static <T extends Enum<?>> T randomEnum(Class<T> clazz){
        int x = random.nextInt(clazz.getEnumConstants().length);
        return clazz.getEnumConstants()[x];
    }

Which you'll use:

randomEnum(MyEnum.class);

I also prefer to use SecureRandom as:

private static final SecureRandom random = new SecureRandom();

Single line

return Letter.values()[new Random().nextInt(Letter.values().length)];

Combining the suggestions of cletus and 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<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: Oops, I forgot the bounded type parameter, <E extends Enum<E>>.


Simple Kotlin Solution

MyEnum.values().random()

random() is a default extension function included in base Kotlin on the Collection object. Kotlin Documentation Link

If you'd like to simplify it with an extension function, try this:

inline fun <reified T : Enum<T>> random(): T = enumValues<T>().random()

// Then call
random<MyEnum>()

To make it static on your enum class. Make sure to import my.package.random in your enum file

MyEnum.randomValue()

// Add this to your enum class
companion object {
    fun randomValue(): MyEnum {
        return random()
    }
}

If you need to do it from an instance of the enum, try this extension

inline fun <reified T : Enum<T>> T.random() = enumValues<T>().random()

// Then call
MyEnum.VALUE.random() // or myEnumVal.random() 

Agree with Stphen C & helios. Better way to fetch random element from Enum is:

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)];
  }
}

Letter lettre = Letter.values()[(int)(Math.random()*Letter.values().length)];