1. Gambaran keseluruhan
Dalam tutorial ini, kita akan membincangkan cara menghasilkan String alfanumerik rawak di Kotlin menggunakan tiga pendekatan yang berbeza: Java Random , Kotlin Random , dan Apache Commons Lang RandomStringUtils .
Kemudian, kita akan menyelesaikan dengan pendekatan berprestasi tinggi.
2. Kebergantungan
Sebelum kita mempelajari tutorial, mari tambahkan kebergantungan Apache Commons Lang ke pom.xml kami :
org.apache.commons commons-lang3 3.8.1
Di samping itu, kami boleh menetapkan beberapa pemalar untuk rujukan kemudian:
const val STRING_LENGTH = 10; const val ALPHANUMERIC_REGEX = "[a-zA-Z0-9]+";
3. Java Rawak
Pertama sekali, mari kita lihat bagaimana menggunakan Java Random untuk menghasilkan String rawak .
Dalam contoh ini, kami akan menggunakan ThreadLocalRandom yang mempunyai contoh Random setiap utas dan melindungi dari perbalahan:
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); }
Dalam contoh ini, kami mendapat 10 aksara alfanumerik rawak dari kumpulan aksara dengan menghasilkan indeksnya, kemudian bergabung dengannya untuk membuat Rentetan rawak .
ThreadLocalRandom tersedia sejak JDK 7 . Kita boleh menggunakan java.util.Random sebagai gantinya. Tetapi jika banyak utas menggunakan contoh Rawak yang sama, benih yang sama dikongsi oleh beberapa utas, menyebabkan perbalahan benang.
Walau bagaimanapun, tidak ThreadLocalRandom tidak rawak adalah kriptografi selamat , kerana ia adalah mungkin untuk meneka nilai seterusnya pulang dari generator. Java memang memberikan java.security.SecureRandom yang jauh lebih perlahan untuk menghasilkan nilai rawak dengan selamat.
4. Kotlin Rawak
Dari Kotlin 1.3, kotlin.random.Random boleh didapati sebagai ciri pelbagai platform . Ia menggunakan java.util.Random dalam JDK 6 dan 7, ThreadLocalRandom dalam JDK 8+ dan math.random dalam Javascript.
Kita boleh mendapatkan String rawak dengan pendekatan yang sama:
val randomString = (1..STRING_LENGTH) .map { i -> kotlin.random.Random.nextInt(0, charPool.size) } .map(charPool::get) .joinToString("");
5. Apache Biasa Lang
Akhirnya, jika kita masih menggunakan Kotlin, kita dapat menggunakan perpustakaan Apache Common Lang untuk menghasilkan String rawak :
@Test fun givenAStringLength_whenUsingApacheCommon_thenReturnAlphanumericString() { val randomString = RandomStringUtils.randomAlphanumeric(STRING_LENGTH); assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))); assertEquals(STRING_LENGTH, randomString.length); }
Dalam contoh ini, kita hanya memanggil RandomStringUtils.randomAlphanumeric untuk mendapatkan String kita dengan panjang yang telah ditentukan.
Kita harus perhatikan bahawa RandomStringUtils menghasilkan nilai rawak dengan menggunakan java.util.Random , yang tidak selamat secara kriptografi seperti yang kita bincangkan di atas. Jadi sekiranya menghasilkan token atau nilai yang diamankan, kita dapat menggunakan CryptoRandom di Apache Commons Crypto atau Java's SecureRandom.
Kami mempunyai tutorial tentang cara menghasilkan String rawak di Java juga untuk membahas topik ini dengan lebih terperinci.
6. Prestasi
Aspek penting dari masing-masing adalah bahawa ia memanggil penjana nombor rawak kami STRING_LENGTH kali. Sekiranya kita membuat banyak tali atau tali panjang , pendekatan ini mungkin terlalu lambat. Walau bagaimanapun, dengan usaha tambahan, kita hanya boleh meminta urutan bait secara rawak, dan kemudian memetakannya ke kumpulan char kami:
@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[random.nextInt(charPool.size)] }.joinToString("") assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) assertEquals(STRING_LENGTH, randomString.length) }
Apa yang menjadikan pendekatan ini kuat ialah, sementara kita masih melakukan STRING_LENGTH pencarian ke charPool kami , kami hanya memanggil penjana rawak kami sekali. Dan, selain menjadi lebih pantas, ini juga dapat mengurangkan perbalahan pada contoh yang dikongsi.
7. Kesimpulannya
Sebagai kesimpulan, kami telah melalui tiga pendekatan untuk menghasilkan rentetan alfanumerik rawak di Kotlin, meneroka nuansa masing-masing. Kemudian, kami beralih gear untuk memeriksa penyelesaian berkinerja tinggi yang dapat digunakan kembali untuk API Kotlin dan Java.
Seperti biasa, kodnya boleh didapati di GitHub.