Gerar uma sequência alfanumérica aleatória no Kotlin

Gerar uma sequência alfanumérica aleatória no Kotlin

1. Visão geral

Neste tutorial, discutiremos como gerar umString alfanumérico aleatório em Kotlin usando três abordagens diferentes: JavaRandom, KotlinRandom e Apache Commons LangRandomStringUtils.

Então, vamos encerrar com uma abordagem de alto desempenho.

2. Dependências

Antes de mergulharmos no tutorial, vamos adicionarApache Commons Lang dependency em nossopom.xml:


    org.apache.commons
    commons-lang3
    3.8.1

Além disso, podemos configurar algumas constantes para referência posterior:

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

3. JavaRandom

Em primeiro lugar, vamos ver comouse Java Random to generate a random String.

Neste exemplo, usaremosThreadLocalRandom, que tem uma instânciaRandom por encadeamento e proteções contra contenção:

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

Neste exemplo, estamosgetting 10 random alphanumeric characters from character pool by generating their indexes, então os juntamos para criar oString. aleatório

ThreadLocalRandom está disponível desde JDK 7Podemos usarjava.util.Random em seu lugar. But if multiple threads use the same instance of Random, the same seed is shared by multiple threads, causing thread contention.

No entanto,neither ThreadLocalRandom nor Random are cryptographically secure, pois é possível adivinhar o próximo valor retornado do gerador. Java fornecejava.security.SecureRandom visivelmente mais lento para gerar um valor aleatório com segurança.

4. KotlinRandom

No Kotlin 1.3,kotlin.random.Random está disponível como um recurso multiplataforma. Ele usajava.util.Random em JDK 6 e 7,ThreadLocalRandom em JDK 8+ eMath.random em Javascript.

Podemos obter umString aleatório com a mesma abordagem:

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

5. Apache Common Lang

Finalmente, se ainda estivermos usando Kotlin, podemosmake 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);
}

Neste exemplo, simplesmente chamamosRandomStringUtils.randomAlphanumeric para obter nossoString com um comprimento predefinido.

Devemos observar queRandomStringUtils geram valores aleatórios usandojava.util.Random, que não é criptograficamente seguro como discutimos acima. So in case of generating a secured token or value, we can use CryptoRandom in Apache Commons Crypto or Java’s SecureRandom.

Temos um tutorial sobrehow to generate a random String in Java também para cobrir este tópico com mais detalhes.

6. atuação

Um aspecto notável de cada um deles é que ele está chamando nosso gerador de números aleatórios deSTRING_LENGTH times. Se estivermos criando muitosStrings ou longosStrings,, essas abordagens podem ser muito lentas. With some extra effort, porém, podemos simplesmente chamar uma sequência aleatória de bytes e, em seguida, mapeá-los para nosso pool de caracteres:

@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)
}

O que torna essa abordagem poderosa é que,while we still do STRING_LENGTH lookups to our charPool, we only call on our random generator once. E, além de ser mais rápida, também pode reduzir a contenção de threads em instâncias compartilhadas.

Além disso, observe que, emborabytes[i] and 0xFF.toByte() and charPool.size.toByte() possa parecer avançado, é apenas uma maneira de garantir que os bytes aleatórios estejam entreandcharPool.size().

7. Conclusão

Em conclusão, passamos por três abordagens para gerar uma string alfanumérica aleatória em Kotlin, explorando as nuances de cada uma. Em seguida, mudamos de marcha para examinar uma solução de alto desempenho que pode ser redirecionada para as APIs Kotlin e Java.

Como sempre, o código pode ser encontradoover on GitHub.