我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。
我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。
理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。
当前回答
我找到了生成随机十六进制编码字符串的解决方案。所提供的单元测试似乎符合我的主要用例。虽然,它比提供的一些其他答案稍微复杂一些。
/**
* Generate a random hex encoded string token of the specified length
*
* @param length
* @return random hex string
*/
public static synchronized String generateUniqueToken(Integer length){
byte random[] = new byte[length];
Random randomGenerator = new Random();
StringBuffer buffer = new StringBuffer();
randomGenerator.nextBytes(random);
for (int j = 0; j < random.length; j++) {
byte b1 = (byte) ((random[j] & 0xf0) >> 4);
byte b2 = (byte) (random[j] & 0x0f);
if (b1 < 10)
buffer.append((char) ('0' + b1));
else
buffer.append((char) ('A' + (b1 - 10)));
if (b2 < 10)
buffer.append((char) ('0' + b2));
else
buffer.append((char) ('A' + (b2 - 10)));
}
return (buffer.toString());
}
@Test
public void testGenerateUniqueToken(){
Set set = new HashSet();
String token = null;
int size = 16;
/* Seems like we should be able to generate 500K tokens
* without a duplicate
*/
for (int i=0; i<500000; i++){
token = Utility.generateUniqueToken(size);
if (token.length() != size * 2){
fail("Incorrect length");
} else if (set.contains(token)) {
fail("Duplicate token generated");
} else{
set.add(token);
}
}
}
其他回答
public static String getRandomString(int length) {
char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
String randomStr = sb.toString();
return randomStr;
}
此外,您可以通过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
我使用的是一个非常简单的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));
}
高效而简短。
/**
* Utility class for generating random Strings.
*/
public interface RandomUtil {
int DEF_COUNT = 20;
Random RANDOM = new SecureRandom();
/**
* Generate a password.
*
* @return the generated password
*/
static String generatePassword() {
return generate(true, true);
}
/**
* Generate an activation key.
*
* @return the generated activation key
*/
static String generateActivationKey() {
return generate(false, true);
}
/**
* Generate a reset key.
*
* @return the generated reset key
*/
static String generateResetKey() {
return generate(false, true);
}
static String generate(boolean letters, boolean numbers) {
int
start = ' ',
end = 'z' + 1,
count = DEF_COUNT,
gap = end - start;
StringBuilder builder = new StringBuilder(count);
while (count-- != 0) {
int codePoint = RANDOM.nextInt(gap) + start;
switch (getType(codePoint)) {
case UNASSIGNED:
case PRIVATE_USE:
case SURROGATE:
count++;
continue;
}
int numberOfChars = charCount(codePoint);
if (count == 0 && numberOfChars > 1) {
count++;
continue;
}
if (letters && isLetter(codePoint)
|| numbers && isDigit(codePoint)
|| !letters && !numbers) {
builder.appendCodePoint(codePoint);
if (numberOfChars == 2)
count--;
}
else
count++;
}
return builder.toString();
}
}
Java提供了一种直接实现这一点的方法。如果你不想要破折号,它们很容易去掉。只需使用uuid.replace(“-”,“”)
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;
}
}
输出
uuid = 2d7428a6-b58c-4008-8575-f05549f16316