我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。
我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。
当前回答
这里有一个简单的一行代码,使用UUID作为字符基础,可以指定(几乎)任何长度。(是的,我知道以前有人建议使用UUID。)
public static String randString(int length) {
return UUID.randomUUID().toString().replace("-", "").substring(0, Math.min(length, 32)) + (length > 32 ? randString(length - 32) : "");
}
其他回答
如果您愿意使用Apache类,可以使用org.Apache.mons.text.RandomStringGenerator(Apache commons文本)。
例子:
RandomStringGenerator randomStringGenerator =
new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
.build();
randomStringGenerator.generate(12); // toUpperCase() if you want
自Apache Commons Lang 3.6以来,RandomStringUtils已被弃用。
另一个解决方案。。。
public static String generatePassword(int passwordLength) {
int asciiFirst = 33;
int asciiLast = 126;
Integer[] exceptions = { 34, 39, 96 };
List<Integer> exceptionsList = Arrays.asList(exceptions);
SecureRandom random = new SecureRandom();
StringBuilder builder = new StringBuilder();
for (int i=0; i<passwordLength; i++) {
int charIndex;
do {
charIndex = random.nextInt(asciiLast - asciiFirst + 1) + asciiFirst;
}
while (exceptionsList.contains(charIndex));
builder.append((char) charIndex);
}
return builder.toString();
}
给定一些字符(AllCharacters),您可以随机选择字符串中的一个字符。然后使用for循环重复获取随机字符。
public class MyProgram {
static String getRandomString(int size) {
String AllCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder(size);
int length = AllCharacters.length();
for (int i = 0; i < size; i++) {
sb.append(AllCharacters.charAt((int)(length * Math.random())));
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(MyProgram.getRandomString(30));
}
}
在沙盒上试试另请参阅其他语言实现随机字符串生成器
使用UUID是不安全的,因为UUID的一部分根本不是随机的。erickson的过程非常简单,但它不会创建相同长度的字符串。以下代码片段应该足够了:
/*
* The random generator used by this class to create random keys.
* In a holder class to defer initialization until needed.
*/
private static class RandomHolder {
static final Random random = new SecureRandom();
public static String randomKey(int length) {
return String.format("%"+length+"s", new BigInteger(length*5/*base 32,2^5*/, random)
.toString(32)).replace('\u0020', '0');
}
}
为什么选择长度*5?让我们假设一个长度为1的随机字符串的简单情况,即一个随机字符。要获得包含所有数字0-9和字符a-z的随机字符,我们需要一个介于0和35之间的随机数来获得每个字符中的一个。
BigInteger提供了一个构造函数来生成一个随机数,均匀分布在0到(2^numBits-1)的范围内。不幸的是,35不是一个可以由2^numBits-1接收的数字。
所以我们有两个选择:要么选择2^5-1=31,要么选择2^ 6-1=63。如果我们选择2^6,我们会得到很多“不必要”/“更长”的数字。因此,2^5是更好的选择,即使我们丢失了四个字符(w-z)。现在要生成特定长度的字符串,我们可以简单地使用2^(length*numBits)-1数字。最后一个问题是,如果我们想要一个具有一定长度的字符串,随机可能会生成一个小数字,因此长度不符合要求,因此我们必须将字符串填充到所需的长度,并加上前缀零。
此外,您可以通过ASCII表中的数据生成任何小写或大写字母,甚至特殊字符。例如,生成从A(DEC 65)到Z(DEC 90)的大写字母:
String generateRandomStr(int min, int max, int size) {
String result = "";
for (int i = 0; i < size; i++) {
result += String.valueOf((char)(new Random().nextInt((max - min) + 1) + min));
}
return result;
}
generateRandomStr(65、90、100)的生成输出;:
TVLPFQJCYFXQDCQSLKUKKILKKHAUFYEXLUQFHDWNMRBIRRRWNXNNZQTINZPCTKLHGHVYWRKEOYNSOFPZBGEECFMCOKWHLHCEWLDZ