Создать случайную буквенно-цифровую строку в Kotlin

Генерация случайной буквенно-цифровой строки в Kotlin

1. обзор

В этом руководстве мы обсудим, как сгенерировать случайный буквенно-цифровойString в Kotlin, используя три разных подхода: JavaRandom, KotlinRandom и Apache Commons LangRandomStringUtils.

Затем мы рассмотрим высокоэффективный подход.

2. зависимости

Прежде чем мы углубимся в руководство, давайте добавимApache Commons Lang dependency в нашpom.xml:


    org.apache.commons
    commons-lang3
    3.8.1

Кроме того, мы можем установить некоторые константы для дальнейшего использования:

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

3. JavaRandom

Прежде всего, давайте посмотрим, какuse Java Random to generate a random String.

В этом примере мы будем использоватьThreadLocalRandom, который имеет экземплярRandom для каждого потока и защищает от конфликтов:

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

В этом примере мыgetting 10 random alphanumeric characters from character pool by generating their indexes, , затем объединяем их вместе, чтобы создать случайныйString.

ThreadLocalRandom доступен с JDK 7 Вместо него можно использоватьjava.util.Random. But if multiple threads use the same instance of Random, the same seed is shared by multiple threads, causing thread contention.

Однакоneither ThreadLocalRandom nor Random are cryptographically secure, так как можно угадать следующее значение, возвращаемое генератором. Java действительно предоставляет заметно более медленныйjava.security.SecureRandom для безопасного создания случайного значения.

4. КотлинRandom

Начиная с Kotlin 1.3kotlin.random.Random доступен как многоплатформенная функция. Он используетjava.util.Random в JDK 6 и 7,ThreadLocalRandom в JDK 8+ иMath.random в Javascript.

Таким же подходом мы можем получить случайныйString:

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

5. Общий язык Apache

Наконец, если мы все еще используем Kotlin, мы можемmake 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);
}

В этом примере мы просто вызываемRandomStringUtils.randomAlphanumeric, чтобы получить нашString с предопределенной длиной.

Следует отметить, чтоRandomStringUtils генерирует случайные значения, используяjava.util.Random, что, как мы обсуждали выше, не является криптографически безопасным. So in case of generating a secured token or value, we can use CryptoRandom in Apache Commons Crypto or Java’s SecureRandom.

У нас также есть руководство поhow to generate a random String in Java, чтобы раскрыть эту тему более подробно.

6. Спектакль

Примечательным аспектом каждого из них является то, что он вызывает наш генератор случайных чиселSTRING_LENGTH times. Если мы создаем многоStrings или longStrings,, эти подходы могут быть слишком медленными. With some extra effort, однако, мы можем просто вызвать случайную последовательность байтов, а затем сопоставить их с нашим пулом символов:

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

Что делает этот подход мощным, так это то, чтоwhile we still do STRING_LENGTH lookups to our charPool, we only call on our random generator once. И, помимо того, что он быстрее, он также может уменьшить конкуренцию потоков в общих экземплярах.

Также обратите внимание, что хотяbytes[i] and 0xFF.toByte() and charPool.size.toByte() может показаться сложным, это всего лишь способ убедиться, что случайные байты находятся междуиcharPool.size().

7. Заключение

В заключение, мы рассмотрели три подхода к генерации случайной буквенно-цифровой строки в Kotlin, исследуя нюансы каждого из них. Затем мы переключились на поиски высокопроизводительного решения, которое можно использовать для API-интерфейсов Kotlin и Java.

Как всегда, код можно найтиover on GitHub.