Générer une chaîne alphanumérique aléatoire dans Kotlin

1. Vue d'ensemble

Dans ce didacticiel, nous verrons comment générer une chaîne alphanumérique aléatoire dans Kotlin en utilisant trois approches différentes: Java Random , Kotlin Random et Apache Commons Lang RandomStringUtils .

Ensuite, nous terminerons par un regard sur une approche haute performance.

2. Dépendances

Avant de plonger dans le didacticiel, ajoutons la dépendance Apache Commons Lang dans notre pom.xml:

 org.apache.commons commons-lang3 3.8.1 

De plus, nous pouvons configurer certaines constantes pour référence ultérieure:

const val STRING_LENGTH = 10; const val ALPHANUMERIC_REGEX = "[a-zA-Z0-9]+"; 

3. Java aléatoire

Tout d'abord, voyons comment utiliser Java Random pour générer une chaîne aléatoire .

Dans cet exemple, nous utiliserons ThreadLocalRandom qui a une instance Random par thread et protège contre les conflits:

private val charPool : List = ('a'..'z') + ('A'..'Z') + ('0'..'9') @Test fun givenAStringLength_whenUsingJava_thenReturnAlphanumericString() { val randomString = ThreadLocalRandom.current() .ints(STRING_LENGTH.toLong(), 0, charPool.size) .asSequence() .map(charPool::get) .joinToString("") assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))); assertEquals(STRING_LENGTH, randomString.length); }

Dans cet exemple, nous obtenons 10 caractères alphanumériques aléatoires à partir du pool de caractères en générant leurs index, puis nous les joignons pour créer la chaîne aléatoire .

ThreadLocalRandom est disponible depuis JDK 7 . Nous pourrions utiliser java.util.Random à la place. Mais si plusieurs threads utilisent la même instance de Random , la même graine est partagée par plusieurs threads, provoquant un conflit de threads.

Cependant, ni ThreadLocalRandom ni Random ne sont sécurisés par cryptographie , car il est possible de deviner la valeur suivante renvoyée par le générateur. Java fournit le java.security.SecureRandom sensiblement plus lent pour générer en toute sécurité une valeur aléatoire.

4. Kotlin aléatoire

Depuis Kotlin 1.3, kotlin.random.Random est disponible en tant que fonctionnalité multiplateforme. Il utilise java.util.Random dans JDK 6 et 7, ThreadLocalRandom dans JDK 8+ et Math.random en Javascript.

Nous pouvons obtenir une chaîne aléatoire avec la même approche:

val randomString = (1..STRING_LENGTH) .map { i -> kotlin.random.Random.nextInt(0, charPool.size) } .map(charPool::get) .joinToString("");

5. Apache Common Lang

Enfin, si nous utilisons toujours Kotlin, nous pouvons utiliser les bibliothèques Apache Common Lang pour générer une chaîne aléatoire :

@Test fun givenAStringLength_whenUsingApacheCommon_thenReturnAlphanumericString() { val randomString = RandomStringUtils.randomAlphanumeric(STRING_LENGTH); assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))); assertEquals(STRING_LENGTH, randomString.length); }

Dans cet exemple, nous appelons simplement RandomStringUtils.randomAlphanumeric pour obtenir notre String avec une longueur prédéfinie.

Nous devons noter que RandomStringUtils génère des valeurs aléatoires en utilisant java.util.Random , qui n'est pas cryptographiquement sécurisé comme nous l'avons vu ci-dessus. Ainsi, en cas de génération d'un jeton ou d'une valeur sécurisée, nous pouvons utiliser CryptoRandom dans Apache Commons Crypto ou SecureRandom de Java .

Nous avons également un tutoriel sur la façon de générer une chaîne aléatoire en Java pour couvrir ce sujet plus en détail.

6. Performance

Un aspect notable de chacun d'entre eux est qu'il appelle notre générateur de nombres aléatoires STRING_LENGTH fois. Si nous créons plusieurs chaînes ou chaînes longues , ces approches peuvent être trop lentes. Avec un effort supplémentaire, cependant, nous pouvons simplement appeler une séquence aléatoire d'octets, puis les mapper à notre pool de caractères:

@Test fun givenAStringLength_whenUsingRandomForBytes_thenReturnAlphanumericString() { val random = SecureRandom() val bytes = ByteArray(STRING_LENGTH) random.nextBytes(bytes) val randomString = (0..bytes.size - 1) .map { i -> charPool[random.nextInt(charPool.size)] }.joinToString("") assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) assertEquals(STRING_LENGTH, randomString.length) } 

Ce qui rend cette approche puissante, c'est que, même si nous effectuons encore des recherches STRING_LENGTH dans notre charPool , nous n'appelons qu'une seule fois notre générateur aléatoire. Et, en plus d'être plus rapide, cela peut également réduire les conflits de thread sur les instances partagées.

7. Conclusion

En conclusion, nous avons parcouru trois approches pour générer une chaîne alphanumérique aléatoire dans Kotlin, en explorant les nuances de chacune. Ensuite, nous avons changé de vitesse pour examiner une solution haute performance qui peut être réutilisée pour les API Kotlin et Java.

Comme toujours, le code peut être trouvé sur GitHub.