Java:从枚举中select一个随机值?

如果我有这样的枚举:

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

什么是随机select一个最好的方法? 它不需要是生产质量防弹,但相当均匀的分布将是很好的。

我可以做这样的事情

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

但有没有更好的办法? 我觉得这是之前解决的问题。

我build议的唯一的事情就是cachingvalues()的结果,因为每个调用都复制一个数组。 另外,不要每次都创build一个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)); } } 

你所有的随机枚举都需要一个方法:

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

结合cletus和helios的build议,

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

编辑:哎呀,我忘了有界的types参数, <E extends Enum>

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

单线

 return Letter.values()[new Random().nextInt(Letter.values().length)]; 
 Letter lettre = Letter.values()[(int)(Math.random()*Letter.values().length)]; 

如果你这样做了testing,你可以使用Quickcheck ( 这是我一直在处理的Java端口 )。

 import static net.java.quickcheck.generator.PrimitiveGeneratorSamples.*; TimeUnit anyEnumValue = anyEnumValue(TimeUnit.class); //one value 

它支持所有原始types,types组合,集合,不同的分布函数,边界等。它支持跑步者执行多个值:

 import static net.java.quickcheck.generator.PrimitiveGeneratorsIterables.*; for(TimeUnit timeUnit : someEnumValues(TimeUnit.class)){ //..test multiple values } 

Quickcheck的优势在于,您可以根据TDD与场景一起工作的规范来定义testing。

有一个函数从数组中选取一个随机值可能是最简单的。 这是比较通用的,而且很直接。

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

像这样调用:

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

在枚举上实现一个随机函数是一个很好的select。

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

这里有一个使用洗牌和stream的版本

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

我会用这个:

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