numeros - metodo random java
Java: ¿elige un valor aleatorio de una enumeración? (12)
Aquí una versión que usa shuffle y streams
List<Direction> letters = Arrays.asList(Direction.values());
Collections.shuffle(letters);
return letters.stream().findFirst().get();
Si tengo una enumeración como esta:
public enum Letter {
A,
B,
C,
//...
}
¿Cuál es la mejor manera de elegir uno al azar? No es necesario que sea de calidad de producción a prueba de balas, pero una distribución bastante uniforme sería agradable.
Podría hacer algo como esto
private Letter randomLetter() {
int pick = new Random().nextInt(Letter.values().length);
return Letter.values()[pick];
}
Pero hay una manera mejor? Siento que esto es algo que ya ha sido resuelto.
Combinando las sugerencias de y 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> {
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)];
}
}
}
Editar: Vaya, olvidé el parámetro de tipo delimitado, <E extends Enum>
.
De acuerdo con Stphen C & helios. Una mejor forma de obtener elementos aleatorios de Enum es:
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)];
}
}
Es más fácil implementar una función aleatoria en la enumeración.
public enum Via {
A, B;
public static Via viaAleatoria(){
Via[] vias = Via.values();
Random generator = new Random();
return vias[generator.nextInt(vias.length)];
}
}
y luego lo llamas de la clase que lo necesitas así
public class Guardia{
private Via viaActiva;
public Guardia(){
viaActiva = Via.viaAleatoria();
}
Esta es probablemente la forma más concisa de lograr su objetivo. Todo lo que necesita hacer es llamar a Letter.getRandom()
y obtendrá una carta enum al azar.
public enum Letter {
A,
B,
C,
//...
public static Letter getRandom() {
return values()[(int) (Math.random() * values().length)];
}
}
Linea sola
return Letter.values()[new Random().nextInt(Letter.values().length)];
Lo único que sugeriría es almacenar en caché el resultado de los values()
porque cada llamada copia una matriz. Además, no crees un Random
cada vez. Conserva uno. Aparte de eso, lo que estás haciendo está bien. Asi que:
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));
}
}
Probablemente sea más fácil tener una función para elegir un valor aleatorio de una matriz. Esto es más genérico y es fácil de llamar.
<T> T randomValue(T[] values) {
return values[mRandom.nextInt(values.length)];
}
Llamar así:
MyEnum value = randomValue(MyEnum.values());
Si hace esto para probar, puede usar Quickcheck ( este es un puerto Java en el que he estado trabajando ).
import static net.java.quickcheck.generator.PrimitiveGeneratorSamples.*;
TimeUnit anyEnumValue = anyEnumValue(TimeUnit.class); //one value
Es compatible con todos los tipos primitivos, composición de tipo, colecciones, diferentes funciones de distribución, límites, etc. Tiene soporte para corredores que ejecutan múltiples valores:
import static net.java.quickcheck.generator.PrimitiveGeneratorsIterables.*;
for(TimeUnit timeUnit : someEnumValues(TimeUnit.class)){
//..test multiple values
}
La ventaja de Quickcheck es que puede definir pruebas basadas en una specification donde TDD simple funciona con escenarios.
Un único método es todo lo que necesita para todas sus enumeraciones aleatorias:
public static <T extends Enum<?>> T randomEnum(Class<T> clazz){
int x = random.nextInt(clazz.getEnumConstants().length);
return clazz.getEnumConstants()[x];
}
Que usarás:
randomEnum(MyEnum.class);
También prefiero usar SecureRandom como:
private static final SecureRandom random = new SecureRandom();
Yo usaría esto:
private static Random random = new Random();
public Object getRandomFromEnum(Class<? extends Enum<?>> clazz) {
return clazz.values()[random.nextInt(clazz.values().length)];
}
Letter lettre = Letter.values()[(int)(Math.random()*Letter.values().length)];