Pick a random value from an enum?

JavaRandomEnums

Java Problem Overview


If I have an enum like this:

public enum Letter {
	A,
	B,
	C,
    //...
}

What is the best way to pick one randomly? It doesn't need to be production quality bulletproof, but a fairly even distribution would be nice.

I could do something like this

private Letter randomLetter() {
	int pick = new Random().nextInt(Letter.values().length);
	return Letter.values()[pick];
}

But is there a better way? I feel like this is something that's been solved before.

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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

Solution 3 - Java

Single line

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

Solution 4 - Java

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>>.

Solution 5 - Java

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() 

Solution 6 - Java

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

Solution 7 - Java

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

Solution 8 - Java

It's probably easiest to have a function to pick a random value from an array. This is more generic, and is straightforward to call.

<T> T randomValue(T[] values) {
    return values[mRandom.nextInt(values.length)];
}

Call like so:

MyEnum value = randomValue(MyEnum.values());

Solution 9 - Java

Here a version that uses shuffle and streams

List<Direction> letters = Arrays.asList(Direction.values());
Collections.shuffle(letters);
return letters.stream().findFirst().get();

Solution 10 - Java

This is probably the most concise way of achieving your goal.All you need to do is to call Letter.getRandom() and you will get a random enum letter.

public enum Letter {
    A,
    B,
    C,
    //...

    public static Letter getRandom() {
        return values()[(int) (Math.random() * values().length)];
    }
}

Solution 11 - Java

If you do this for testing you could use Quickcheck (this is a Java port I've been working on).

import static net.java.quickcheck.generator.PrimitiveGeneratorSamples.*;

TimeUnit anyEnumValue = anyEnumValue(TimeUnit.class); //one value

It supports all primitive types, type composition, collections, different distribution functions, bounds etc. It has support for runners executing multiple values:

import static net.java.quickcheck.generator.PrimitiveGeneratorsIterables.*;

for(TimeUnit timeUnit : someEnumValues(TimeUnit.class)){
    //..test multiple values
}

The advantage of Quickcheck is that you can define tests based on a specification where plain TDD works with scenarios.

Solution 12 - Java

I guess that this single-line-return method is efficient enough to be used in such a simple job:

public enum Day {
    SUNDAY,
    MONDAY,
    THURSDAY,
    WEDNESDAY,
    TUESDAY,
    FRIDAY;

    public static Day getRandom() {
        return values()[(int) (Math.random() * values().length)];
    }

    public static void main(String[] args) {
        System.out.println(Day.getRandom());
    }
}

Solution 13 - Java

It´s eaiser to implement an random function on the enum.

public enum Via {
	A, B;

public static Via viaAleatoria(){
	Via[] vias = Via.values();
	Random generator = new Random();
	return vias[generator.nextInt(vias.length)];
	}
}

and then you call it from the class you need it like this

public class Guardia{
private Via viaActiva;

public Guardia(){
	viaActiva = Via.viaAleatoria();
}

Solution 14 - Java

I would use this:

private static Random random = new Random();

public Object getRandomFromEnum(Class<? extends Enum<?>> clazz) {
    return clazz.values()[random.nextInt(clazz.values().length)];
}

Solution 15 - Java

enum ShapeColor { Blue, Yellow, Red, Green, White, }

    Random random=new Random();
    ShapeColor[] values=ShapeColor.values();
    int size=values.length;
    return values[random.nextInt(size)];

Solution 16 - Java

public static Letter randomLetter() {
    return List.of(values()).get(Random.randomInt(List.of(values()).size()));

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick HeinerView Question on Stackoverflow
Solution 1 - JavacletusView Answer on Stackoverflow
Solution 2 - JavaEldelshellView Answer on Stackoverflow
Solution 3 - JavaMohamed Taher AlrefaieView Answer on Stackoverflow
Solution 4 - JavatrashgodView Answer on Stackoverflow
Solution 5 - JavaGiboltView Answer on Stackoverflow
Solution 6 - JavaanonymousView Answer on Stackoverflow
Solution 7 - JavaDeeptiView Answer on Stackoverflow
Solution 8 - JavaJoseph ThomsonView Answer on Stackoverflow
Solution 9 - Javamajor seitanView Answer on Stackoverflow
Solution 10 - JavaAdilli AdilView Answer on Stackoverflow
Solution 11 - JavaThomas JungView Answer on Stackoverflow
Solution 12 - JavaMuhammad ZidanView Answer on Stackoverflow
Solution 13 - JavaFoleaView Answer on Stackoverflow
Solution 14 - Javauser5910225View Answer on Stackoverflow
Solution 15 - JavaZeeshan LiaqatView Answer on Stackoverflow
Solution 16 - JavaIzzyView Answer on Stackoverflow