Idiomatic way to generate a random alphanumeric string in Kotlin

Kotlin

Kotlin Problem Overview


I can generate a random sequence of numbers in a certain range like the following:

fun ClosedRange<Int>.random() = Random().nextInt(endInclusive - start) +  start
fun generateRandomNumberList(len: Int, low: Int = 0, high: Int = 255): List<Int> {
  (0..len-1).map {
    (low..high).random()
  }.toList()
}

Then I'll have to extend List with:

fun List<Char>.random() = this[Random().nextInt(this.size)]

Then I can do:

fun generateRandomString(len: Int = 15): String{
  val alphanumerics = CharArray(26) { it -> (it + 97).toChar() }.toSet()
      .union(CharArray(9) { it -> (it + 48).toChar() }.toSet())
  return (0..len-1).map {
      alphanumerics.toList().random()
  }.joinToString("")
}

But maybe there's a better way?

Kotlin Solutions


Solution 1 - Kotlin

Since Kotlin 1.3 you can do this:

fun getRandomString(length: Int) : String {
    val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
    return (1..length)
        .map { allowedChars.random() }
        .joinToString("")
}

Solution 2 - Kotlin

Lazy folks would just do

java.util.UUID.randomUUID().toString()

You can not restrict the character range here, but I guess it's fine in many situations anyway.

Solution 3 - Kotlin

Assuming you have a specific set of source characters (source in this snippet), you could do this:

val source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
java.util.Random().ints(outputStrLength, 0, source.length)
        .asSequence()
        .map(source::get)
        .joinToString("")

Which gives strings like "LYANFGNPNI" for outputStrLength = 10.

The two important bits are

  1. Random().ints(length, minValue, maxValue) which produces a stream of length random numbers each from minValue to maxValue-1, and
  2. asSequence() which converts the not-massively-useful IntStream into a much-more-useful Sequence<Int>.

Solution 4 - Kotlin

Using Collection.random() from Kotlin 1.3:

// Descriptive alphabet using three CharRange objects, concatenated
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')

// Build list from 20 random samples from the alphabet,
// and convert it to a string using "" as element separator
val randomString: String = List(20) { alphabet.random() }.joinToString("")

Solution 5 - Kotlin

Without JDK8:

fun ClosedRange<Char>.randomString(length: Int) = 
    (1..length)
    	.map { (Random().nextInt(endInclusive.toInt() - start.toInt()) + start.toInt()).toChar() }
    	.joinToString("")

usage:

('a'..'z').randomString(6)

Solution 6 - Kotlin

To define it for a defined length:

val randomString = UUID.randomUUID().toString().substring(0,15)

where 15 is the number of characters

Solution 7 - Kotlin

('A'..'z').map { it }.shuffled().subList(0, 4).joinToString("")

Solution 8 - Kotlin

Using Kotlin 1.3:

This method uses an input of your desired string length desiredStrLength as an Integer and returns a random alphanumeric String of your desired string length.

fun randomAlphaNumericString(desiredStrLength: Int): String {
    val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')

    return (1..desiredStrLength)
        .map{ kotlin.random.Random.nextInt(0, charPool.size) }
        .map(charPool::get)
        .joinToString("")
}

If you prefer unknown length of alphanumeric (or at least a decently long string length like 36 in my example below), this method can be used:

fun randomAlphanumericString(): String {
    val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
    val outputStrLength = (1..36).shuffled().first()

    return (1..outputStrLength)
        .map{ kotlin.random.Random.nextInt(0, charPool.size) }
        .map(charPool::get)
        .joinToString("")
}

Solution 9 - Kotlin

Or use coroutine API for the true Kotlin spirit:

buildSequence { val r = Random(); while(true) yield(r.nextInt(24)) }
   .take(10)
   .map{(it+ 65).toChar()}
   .joinToString("")

Solution 10 - Kotlin

Building off the answer from Paul Hicks, I wanted a custom string as input. In my case, upper and lower-case alphanumeric characters. Random().ints(...) also wasn't working for me, as it required an API level of 24 on Android to use it.

This is how I'm doing it with Kotlin's Random abstract class:

import kotlin.random.Random

object IdHelper {

    private val ALPHA_NUMERIC = ('0'..'9') + ('A'..'Z') + ('a'..'z')
    private const val LENGTH = 20

    fun generateId(): String {
        return List(LENGTH) { Random.nextInt(0, ALPHA_NUMERIC.size) }
                .map { ALPHA_NUMERIC[it] }
                .joinToString(separator = "")
    }
}

The process and how this works is similar to a lot of the other answers already posted here:

  1. Generate a list of numbers of length LENGTH that correspond to the index values of the source string, which in this case is ALPHA_NUMERIC
  2. Map those numbers to the source string, converting each numeric index to the character value
  3. Convert the resulting list of characters to a string, joining them with the empty string as the separator character.
  4. Return the resulting string.

Usage is easy, just call it like a static function: IdHelper.generateId()

Solution 11 - Kotlin

I use the following code to generate random words and sentences.

val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')

val randomWord: String = List((1..10).random()) { alphabet.random() }.joinToString("")

val randomSentence: String = (1..(1..10).random()).joinToString(" ") { List((1..10).random()) { alphabet.random() }.joinToString("") }

Solution 12 - Kotlin

fun randomAlphaNumericString(@IntRange(from = 1, to = 62) lenght: Int): String {
    val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
    return alphaNumeric.shuffled().take(lenght).joinToString("")
}

Solution 13 - Kotlin

the question is old already, but I think another great solution (should work since Kotlin 1.3) would be the following:

// Just a simpler way to create a List of characters, as seen in other answers
// You can achieve the same effect by declaring it as a String "ABCDEFG...56789"
val alphanumeric = ('A'..'Z') + ('a'..'z') + ('0'..'9')

fun generateAlphanumericString(length: Int) : String {
    // The buildString function will create a StringBuilder
    return buildString {
        // We will repeat length times and will append a random character each time
        // This roughly matches how you would do it in plain Java
        repeat(length) { append(alphanumeric.random()) }
    }
}

Solution 14 - Kotlin

The best way I think:

fun generateID(size: Int): String {
    val source = "A1BCDEF4G0H8IJKLM7NOPQ3RST9UVWX52YZab1cd60ef2ghij3klmn49opq5rst6uvw7xyz8"
    return (source).map { it }.shuffled().subList(0, size).joinToString("")
}

Solution 15 - Kotlin

You can use RandomStringUtils.randomAlphanumeric(min: Int, max: Int) -> String from apache-commons-lang3

Solution 16 - Kotlin

Here's a cryptographically secure version of it, or so I believe:

fun randomString(len: Int): String {
    val random = SecureRandom()
    val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray()
    return (1..len).map { chars[random.nextInt(chars.size)] }.joinToString("")
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbreezymriView Question on Stackoverflow
Solution 1 - KotlinWhiteAngelView Answer on Stackoverflow
Solution 2 - KotlinHolger BrandlView Answer on Stackoverflow
Solution 3 - KotlinPaul HicksView Answer on Stackoverflow
Solution 4 - KotlinTheOperatorView Answer on Stackoverflow
Solution 5 - KotlinAndrzej SawoniewiczView Answer on Stackoverflow
Solution 6 - KotlinJöckerView Answer on Stackoverflow
Solution 7 - KotlinLouis SaglioView Answer on Stackoverflow
Solution 8 - KotlinjojoView Answer on Stackoverflow
Solution 9 - KotlinHolger BrandlView Answer on Stackoverflow
Solution 10 - KotlinKyle FalconerView Answer on Stackoverflow
Solution 11 - KotlinM-WajeehView Answer on Stackoverflow
Solution 12 - KotlinSefa GürelView Answer on Stackoverflow
Solution 13 - KotlinFabb111View Answer on Stackoverflow
Solution 14 - KotlinMickael BelhassenView Answer on Stackoverflow
Solution 15 - KotlinjchiavaroView Answer on Stackoverflow
Solution 16 - KotlinbinwiederhierView Answer on Stackoverflow