Java 从枚举中选择一个随机值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1972392/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:56:40  来源:igfitidea点击:

Pick a random value from an enum?

javarandomenums

提问by Nick Heiner

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.

但是有更好的方法吗?我觉得这是以前已经解决的问题。

采纳答案by cletus

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

我唯一建议的是缓存结果,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));
  }
}

回答by trashgod

Combining the suggestions of cletusand helios,

结合cletushelios的建议,

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

编辑:糟糕,我忘记了有界类型参数<E extends Enum<E>>.

回答by Thomas Jung

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

如果您这样做是为了测试,您可以使用Quickcheck这是我一直在研究的 Java 端口)。

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 specificationwhere plain TDD works with scenarios.

Quickcheck 的优点是您可以根据规范定义测试,其中纯 TDD 与场景配合使用。

回答by anonymous

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

回答by Eldelshell

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 SecureRandomas:

我也更喜欢使用SecureRandom作为:

private static final SecureRandom random = new SecureRandom();

回答by Joseph Thomson

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

回答by Folea

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

回答by Deepti

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

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

回答by Mohamed Taher Alrefaie

Single line

单线

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

回答by major seitan

Here a version that uses shuffle and streams

这是一个使用 shuffle 和流的版本

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