Java中生成随机字母数字字符串的方法
技术背景
在Java开发中,经常会有生成随机字母数字字符串的需求,比如作为唯一的会话/密钥标识符。对于一些简单的应用场景,需要生成的字符串在一定数量(如500K+)内“大概率”保持唯一。同时,不同的应用场景对字符串的安全性、长度、字符集等方面有不同的要求。
实现步骤
方法一:自定义类实现
可以创建一个自定义类来实现随机字符串的生成,代码如下:
import java.util.Objects;
import java.util.Random;
import java.util.Locale;
public class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}
使用示例:
import java.util.concurrent.ThreadLocalRandom;
import java.security.SecureRandom;
public class Main {
public static void main(String[] args) {
// 创建一个不安全的8字符标识符生成器
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
System.out.println(gen.nextString());
// 创建一个安全的会话标识符生成器
RandomString session = new RandomString();
System.out.println(session.nextString());
// 创建一个易于阅读的代码生成器
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
System.out.println(tickets.nextString());
}
}
方法二:使用UUID类
Java的UUID类可以方便地生成随机字符串,代码如下:
import java.util.UUID;
public class randomStringGenerator {
public static void main(String[] args) {
System.out.println(generateString());
}
public static String generateString() {
String uuid = UUID.randomUUID().toString();
return "uuid = " + uuid.replace("-", "");
}
}
方法三:简单字符拼接实现
import java.security.SecureRandom;
public class RandomStringSimple {
static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static SecureRandom rnd = new SecureRandom();
public static String randomString(int len) {
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
}
public static void main(String[] args) {
System.out.println(randomString(12));
}
}
核心代码
自定义类实现核心代码
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
UUID类实现核心代码
String uuid = UUID.randomUUID().toString();
return uuid.replace("-", "");
简单字符拼接实现核心代码
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
最佳实践
- 安全性:如果生成的字符串用于安全敏感场景,如会话标识符,建议使用SecureRandom类来保证随机性和安全性。
- 长度选择:根据具体需求选择合适的字符串长度,考虑“生日悖论”,确保在预期的生成数量内碰撞概率足够低。
- 字符集选择:根据应用场景选择合适的字符集,避免使用可能引起编码问题的字符。
常见问题
- 碰撞问题:当生成的字符串数量较多时,可能会出现碰撞(即生成相同的字符串)。可以通过增加字符串长度或使用更大的字符集来降低碰撞概率。
- 性能问题:SecureRandom类的初始化和使用可能会带来一定的性能开销,尤其是在需要大量生成随机字符串的场景下。可以考虑缓存SecureRandom实例以提高性能。
- URL安全问题:如果生成的字符串将用于URL中,需要确保字符集不包含可能导致URL编码问题的字符,或者使用URL安全的编码方式。