我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。
我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。
当前回答
我使用的是一个非常简单的Java8解决方案。只需根据您的需求进行定制。
...
import java.security.SecureRandom;
...
//Generate a random String of length between 10 to 20.
//Length is also randomly generated here.
SecureRandom random = new SecureRandom();
String sampleSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
int stringLength = random.ints(1, 10, 21).mapToObj(x -> x).reduce((a, b) -> a).get();
String randomString = random.ints(stringLength, 0, sampleSet.length() - 1)
.mapToObj(x -> sampleSet.charAt(x))
.collect(Collector
.of(StringBuilder::new, StringBuilder::append,
StringBuilder::append, StringBuilder::toString));
我们可以使用它生成如下的字母数字随机字符串(返回的字符串将强制包含一些非数字字符以及一些数字字符):
public String generateRandomString() {
String sampleSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
String sampleSetNumeric = "0123456789";
String randomString = getRandomString(sampleSet, 10, 21);
String randomStringNumeric = getRandomString(sampleSetNumeric, 10, 21);
randomString = randomString + randomStringNumeric;
//Convert String to List<Character>
List<Character> list = randomString.chars()
.mapToObj(x -> (char)x)
.collect(Collectors.toList());
Collections.shuffle(list);
//This is needed to force a non-numeric character as the first String
//Skip this for() if you don't need this logic
for(;;) {
if(Character.isDigit(list.get(0))) Collections.shuffle(list);
else break;
}
//Convert List<Character> to String
randomString = list.stream()
.map(String::valueOf)
.collect(Collectors.joining());
return randomString;
}
//Generate a random number between the lower bound (inclusive) and upper bound (exclusive)
private int getRandomLength(int min, int max) {
SecureRandom random = new SecureRandom();
return random.ints(1, min, max).mapToObj(x -> x).reduce((a, b) -> a).get();
}
//Generate a random String from the given sample string, having a random length between the lower bound (inclusive) and upper bound (exclusive)
private String getRandomString(String sampleSet, int min, int max) {
SecureRandom random = new SecureRandom();
return random.ints(getRandomLength(min, max), 0, sampleSet.length() - 1)
.mapToObj(x -> sampleSet.charAt(x))
.collect(Collector
.of(StringBuilder::new, StringBuilder::append,
StringBuilder::append, StringBuilder::toString));
}
其他回答
我正在使用Apache Commons的库生成一个字母数字字符串:
import org.apache.commons.lang3.RandomStringUtils;
String keyLength = 20;
RandomStringUtils.randomAlphanumeric(keylength);
它又快又简单!
您可以在没有外部库的情况下在一行中完成此操作。
int length = 12;
String randomString = new Random().ints(48, 122).filter(i -> (i < 58 || i > 64) && (i < 91 || i > 96)).limit(length).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
System.out.print(randomString);
我将长度分隔成一个参数,并添加了一行以打印结果。
此代码创建一个以字母数字ascii范围为界的随机整数流。然后它过滤掉一些符号,因为字母数字范围不是连续的。然后它限制长度并将结果收集到字符串中。
因为这种方法丢弃了它生成的大约20%的数字/字符(因为它们是符号),所以对性能的影响很小。
我不觉得它特别可读,但我认为没有人在一行中提出过本机Java解决方案。
我使用的是一个非常简单的Java8解决方案。只需根据您的需求进行定制。
...
import java.security.SecureRandom;
...
//Generate a random String of length between 10 to 20.
//Length is also randomly generated here.
SecureRandom random = new SecureRandom();
String sampleSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
int stringLength = random.ints(1, 10, 21).mapToObj(x -> x).reduce((a, b) -> a).get();
String randomString = random.ints(stringLength, 0, sampleSet.length() - 1)
.mapToObj(x -> sampleSet.charAt(x))
.collect(Collector
.of(StringBuilder::new, StringBuilder::append,
StringBuilder::append, StringBuilder::toString));
我们可以使用它生成如下的字母数字随机字符串(返回的字符串将强制包含一些非数字字符以及一些数字字符):
public String generateRandomString() {
String sampleSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
String sampleSetNumeric = "0123456789";
String randomString = getRandomString(sampleSet, 10, 21);
String randomStringNumeric = getRandomString(sampleSetNumeric, 10, 21);
randomString = randomString + randomStringNumeric;
//Convert String to List<Character>
List<Character> list = randomString.chars()
.mapToObj(x -> (char)x)
.collect(Collectors.toList());
Collections.shuffle(list);
//This is needed to force a non-numeric character as the first String
//Skip this for() if you don't need this logic
for(;;) {
if(Character.isDigit(list.get(0))) Collections.shuffle(list);
else break;
}
//Convert List<Character> to String
randomString = list.stream()
.map(String::valueOf)
.collect(Collectors.joining());
return randomString;
}
//Generate a random number between the lower bound (inclusive) and upper bound (exclusive)
private int getRandomLength(int min, int max) {
SecureRandom random = new SecureRandom();
return random.ints(1, min, max).mapToObj(x -> x).reduce((a, b) -> a).get();
}
//Generate a random String from the given sample string, having a random length between the lower bound (inclusive) and upper bound (exclusive)
private String getRandomString(String sampleSet, int min, int max) {
SecureRandom random = new SecureRandom();
return random.ints(getRandomLength(min, max), 0, sampleSet.length() - 1)
.mapToObj(x -> sampleSet.charAt(x))
.collect(Collector
.of(StringBuilder::new, StringBuilder::append,
StringBuilder::append, StringBuilder::toString));
}
public class Utils {
private final Random RANDOM = new SecureRandom();
private final String ALPHABET = "0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
private String generateRandomString(int length) {
StringBuffer buffer = new StringBuffer(length);
for (int i = 0; i < length; i++) {
buffer.append(ALPHABET.charAt(RANDOM.nextInt(ALPHABET.length())));
}
return new String(buffer);
}
}
一个简单的解决方案,但它只使用小写和数字:
Random r = new java.util.Random ();
String s = Long.toString (r.nextLong () & Long.MAX_VALUE, 36);
大小约为12位数,以36为基数,这样就无法进一步改进。当然,您可以附加多个实例。