このような列挙型がある場合:
public enum Letter {
A,
B,
C,
//...
}
ランダムに1つを選ぶ最良の方法は何ですか?それは、生産品質の防弾である必要はありませんが、かなり均一な分布がいいでしょう。
このようなことができます
private Letter randomLetter() {
int pick = new Random().nextInt(Letter.values().length);
return Letter.values()[pick];
}
しかし、もっと良い方法はありますか?これは以前に解決されたものだと思います。
私が提案する唯一のことは、各呼び出しが配列をコピーするため、values()
の結果をキャッシュすることです。また、毎回Random
を作成しないでください。 1つ保持します。それ以外はあなたがやっていることは大丈夫です。そう:
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つのメソッドだけです。
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();
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>>
を忘れてしまいました。
単線
return Letter.values()[new Random().nextInt(Letter.values().length)];
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)];
}
}
ここではシャッフルとストリームを使用するバージョン
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)];
}
}
Letter lettre = Letter.values()[(int)(Math.random()*Letter.values().length)];
配列からランダムな値を選択する関数を使用するのがおそらく最も簡単です。これはより一般的で、簡単に呼び出すことができます。
<T> T randomValue(T[] values) {
return values[mRandom.nextInt(values.length)];
}
次のように呼び出します:
MyEnum value = randomValue(MyEnum.values());
テストのためにこれを行う場合は、 Quickcheck ( これはJava作業中のポートです )を使用できます。
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の利点は、プレーンTDDがシナリオで機能する specification に基づいてテストを定義できることです。
列挙にランダム関数を実装する方が簡単です。
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();
}
私はこれを使用します:
private static Random random = new Random();
public Object getRandomFromEnum(Class<? extends Enum<?>> clazz) {
return clazz.values()[random.nextInt(clazz.values().length)];
}