如果我有这样的枚举:
public enum Letter {
A,
B,
C,
//...
}
随机选择一个最好的方法是什么?它不需要是生产质量的防弹,但是相当均匀的分布会很好。
我可以做这样的事情
private Letter randomLetter() {
int pick = new Random().nextInt(Letter.values().length);
return Letter.values()[pick];
}
但是有更好的方法吗?我觉得这是以前已经解决的问题。
答案 0 :(得分:125)
我唯一建议的是缓存values()
的结果,因为每次调用都会复制一个数组。另外,不要每次都创建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));
}
}
答案 1 :(得分:98)
您需要的所有随机枚举都需要一种方法:
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();
答案 2 :(得分:41)
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)];
}
}
}
编辑:糟糕,我忘记了有界类型参数<E extends Enum<E>>
。
答案 3 :(得分:24)
单行
return Letter.values()[new Random().nextInt(Letter.values().length)];
答案 4 :(得分:10)
同意Stphen C&amp;赫利俄斯。从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)];
}
}
答案 5 :(得分:8)
MyEnum.values().random()
random()
是Collection
对象上基础Kotlin中包含的默认扩展功能。 Kotlin Documentation Link
inline fun <reified T : Enum<T>> random(): T = enumValues<T>().random()
// Then call
random<MyEnum>()
使其在您的枚举类上静态。确保在您的枚举文件中导入my.package.random
MyEnum.randomValue()
// Add this to your enum class
companion object {
fun randomValue(): MyEnum {
return random()
}
}
inline fun <reified T : Enum<T>> T.random() = enumValues<T>().random()
// Then call
MyEnum.VALUE.random() // or myEnumVal.random()
答案 6 :(得分:4)
Letter lettre = Letter.values()[(int)(Math.random()*Letter.values().length)];
答案 7 :(得分:4)
这可能是实现目标的最简洁方式。您只需拨打Letter.getRandom()
即可获得随机枚举字母。
public enum Letter {
A,
B,
C,
//...
public static Letter getRandom() {
return values()[(int) (Math.random() * values().length)];
}
}
答案 8 :(得分:3)
如果你这样做进行测试,可以使用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
它支持所有原始类型,类型组合,集合,不同的分布函数,边界等。它支持执行多个值的运行程序:
import static net.java.quickcheck.generator.PrimitiveGeneratorsIterables.*;
for(TimeUnit timeUnit : someEnumValues(TimeUnit.class)){
//..test multiple values
}
Quickcheck的优势在于您可以基于specification定义测试,其中普通TDD适用于场景。
答案 9 :(得分:3)
最简单的方法是从数组中选择一个随机值。这是更通用的,并且可以直接调用。
<T> T randomValue(T[] values) {
return values[mRandom.nextInt(values.length)];
}
这样打电话:
MyEnum value = randomValue(MyEnum.values());
答案 10 :(得分:3)
这是一个使用shuffle和流的版本
List<Direction> letters = Arrays.asList(Direction.values());
Collections.shuffle(letters);
return letters.stream().findFirst().get();
答案 11 :(得分:2)
在枚举上实现随机函数更容易。
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();
}
答案 12 :(得分:2)
我会用这个:
private static Random random = new Random();
public Object getRandomFromEnum(Class<? extends Enum<?>> clazz) {
return clazz.values()[random.nextInt(clazz.values().length)];
}
答案 13 :(得分:1)
我猜想这种单行返回方法足够有效,可以用于如此简单的工作:
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());
}
}