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

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

1. Vue d'ensemble

Dans ce didacticiel, nous allons expliquer comment générer unString alphanumérique aléatoire dans Kotlin en utilisant trois approches différentes: JavaRandom, KotlinRandom et Apache Commons LangRandomStringUtils.

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

2. Les dépendances

Avant de plonger dans le didacticiel, ajoutons lesApache Commons Lang dependency dans nospom.xml:


    org.apache.commons
    commons-lang3
    3.8.1

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

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

3. JavaRandom

Tout d'abord, voyons commentuse Java Random to generate a random String.

Dans cet exemple, nous utiliseronsThreadLocalRandom qui a une instanceRandom 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 sommesgetting 10 random alphanumeric characters from character pool by generating their indexes, puis les joignons ensemble pour créer lesString. aléatoires

ThreadLocalRandom est disponible depuis le JDK 7 Nous pourrions utiliserjava.util.Random à la place. But if multiple threads use the same instance of Random, the same seed is shared by multiple threads, causing thread contention.

Cependant,neither ThreadLocalRandom nor Random are cryptographically secure, car il est possible de deviner la prochaine valeur renvoyée par le générateur. Java fournit lesjava.security.SecureRandom sensiblement plus lents pour générer en toute sécurité une valeur aléatoire.

4. KotlinRandom

À partir de Kotlin 1.3,kotlin.random.Random est disponible en tant que fonctionnalité multiplateforme. Il utilisejava.util.Random dans les JDK 6 et 7,ThreadLocalRandom dans JDK 8+ etMath.random en Javascript.

Nous pouvons obtenir unString 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 pouvonsmake use of Apache Common Lang libraries to generate a random String:

@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 simplementRandomStringUtils.randomAlphanumeric pour obtenir nosString avec une longueur prédéfinie.

Nous devons noter queRandomStringUtils génère des valeurs aléatoires en utilisantjava.util.Random, qui n'est pas cryptographiquement sécurisé comme nous l'avons vu ci-dessus. So in case of generating a secured token or value, we can use CryptoRandom in Apache Commons Crypto or Java’s SecureRandom.

Nous avons également un tutoriel surhow to generate a random String in 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éatoiresSTRING_LENGTH times. Si nous créons plusieursStrings ou longsStrings,, ces approches peuvent être trop lentes. With some extra effort, 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.get((bytes[i] and 0xFF.toByte() and (charPool.size-1).toByte()).toInt())
    }.joinToString("")

    assert(randomString.matches(Regex(ALPHANUMERIC_REGEX)))
    assertEquals(STRING_LENGTH, randomString.length)
}

Ce qui rend cette approche puissante, c'est que,while we still do STRING_LENGTH lookups to our charPool, we only call on our random generator once. Et, en plus d'être plus rapide, cela peut également réduire les conflits de thread sur les instances partagées.

Notez également que sibytes[i] and 0xFF.toByte() and charPool.size.toByte() peut sembler avancé, c'est juste un moyen de s'assurer que les octets aléatoires sont entreandcharPool.size().

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. Nous avons ensuite passé à la vitesse supérieure pour examiner une solution hautes performances pouvant être réutilisée pour les API Kotlin et Java.

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