1. Overview
In this tutorial, we’ll discuss how to generate a random alphanumeric String in Kotlin using three different approaches: Java Random, Kotlin Random, and RandomStringUtils from the Apache Commons Lang library.
2. Dependencies
Before we dive into the tutorial, let’s add the Apache Commons Lang dependency to our pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
In addition, we can set up a constant to define the length of the random string we’ll generate:
const val STRING_LENGTH = 10
3. About Tests
In this tutorial, we’ll use unit test assertions to verify if each approach gives the expected result. However, the randomness test itself is a complex topic. Therefore, for simplicity, we’ll execute each solution 10000 times and expect the produced 10000 strings to be all different. Further, each string should have the length 10 and match the “^[0-9a-zA-Z]+$” regex.
We’ll make each solution a Kotlin function, which takes no argument and returns the random string.
Therefore, let’s first create a high-order function to verify the functions:
private fun verifyTheSolution(randomFunc: () -> String) {
val randoms = List(10_000) { randomFunc() }
assertTrue { randoms.all { it.matches(Regex("^[0-9a-zA-Z]+$") } }
assertTrue { randoms.none { it.length != STRING_LENGTH } }
assertTrue { randoms.size == randoms.toSet().size } //no duplicates
}
As the code above shows, the verifyTheSolution() function receives a lambda expression, which would be the solution function to test.
Next, we invoke the randomFunc() function 10000 times and store the result in the randoms list.
Then, we can apply the earlier-mentioned verifications.
Now, it’s time to generate the random strings.
4. Java Random
First of all, let’s look at how to use Java Random to generate a random String.
In this example, we’ll use ThreadLocalRandom, which has a Random instance per thread and safeguards against contention:
val charPool : List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
fun randomStringByJavaRandom() = ThreadLocalRandom.current()
.ints(STRING_LENGTH.toLong(), 0, charPool.size)
.asSequence()
.map(charPool::get)
.joinToString("")
Here, we’re getting 10 random alphanumeric characters from the character pool by generating their indexes, then joining them together to create the random String.
ThreadLocalRandom has been available since JDK 7*.* We could use java.util.Random instead. But if multiple threads use the same instance of Random, the same seed is shared by multiple threads, causing thread contention.
However, neither ThreadLocalRandom nor Random are cryptographically secure, as it’s possible to guess the next value returned from the generator. Java does provide a noticeably slower java.security.SecureRandom to securely generate a random value.
Next, let’s see whether this function can pass our verifyTheSolution() test:
@Test
fun givenAStringLength_whenUsingJava_thenReturnAlphanumericString() {
verifyTheSolution { randomStringByJavaRandom() }
}
If we run the test above, it passes.
5. Kotlin Random
From Kotlin 1.3, kotlin.random.Random is available as a multiplatform feature. It uses java.util.Random in JDK 6 and 7, ThreadLocalRandom in JDK 8+, and Math.random in Javascript.
We can get a random String with the same approach:
fun randomStringByKotlinRandom() = (1..STRING_LENGTH)
.map { Random.nextInt(0, charPool.size).let { charPool[it] } }
.joinToString("")
Also, it passes our test:
@Test
fun givenAStringLength_whenUsingKotlin_thenReturnAlphanumericString() {
verifyTheSolution { randomStringByKotlinRandom() }
}
It’s worth mentioning that Kotlin’s Collection offers the random() function. It allows us to retrieve one element from the collection randomly. Therefore, we can simplify our solution using random():
fun randomStringByKotlinCollectionRandom() = List(STRING_LENGTH) { charPool.random() }.joinToString("")
As we can see, charPool.random() makes the function easier to read and understand.
Unsurprisingly, this solution passes our test too:
@Test
fun givenAStringLength_whenUsingKotlinCollectionRandom_thenReturnAlphanumericString() {
verifyTheSolution { randomStringByKotlinCollectionRandom() }
}
6. Apache Common Lang
Finally, in Kotlin, we can still make use of Apache Common Lang libraries to generate a random String:
fun randomStringByApacheCommons() = RandomStringUtils.randomAlphanumeric(STRING_LENGTH)
In this example, we simply call RandomStringUtils.randomAlphanumeric() to get our String with a predefined length.
We should note that RandomStringUtils generates random values by using java.util.Random, which isn’t cryptographically secure, as we discussed above. So for generating a secured token or value, we can use CryptoRandom in Apache Commons Crypto or Java’s SecureRandom.
We have a tutorial about how to generate a random String in Java as well to cover this topic in more detail.
If we test this function with our verifyTheSolution() function, it passes too:
@Test
fun givenAStringLength_whenUsingKotlinCollectionRandom_thenReturnAlphanumericString() {
verifyTheSolution { randomStringByKotlinCollectionRandom() }
}
7. Conclusion
In this article, we’ve gone through three approaches to generate a random alphanumeric string in Kotlin, exploring the nuances of each.
As always, the code can be found over on GitHub.