在Java中如何生成随机字符串

76

我有一个名为 Student 的对象,它有 studentNamestudentIdstudentAddress 等属性。对于 studentId,我需要生成七个数字字符的随机字符串,例如:

studentId = getRandomId();
studentId = "1234567" <-- from the random generator.

我必须确保没有重复的id。


3
如果我正确理解了你的问题,你想生成一个随机数R,使得1,000,000 <= R <= 9,999,999,并将其转换为字符串? - MSalters
1
先生成一个随机数,然后将其转换为字符串,这样会更容易吗? - chandra wibowo
1
那么,作业任务完成得怎么样了? - james.garriss
4
我认为这三行单行代码非常有用。
  1. Long.toHexString(Double.doubleToLongBits(Math.random())); 将随机生成的Double类型数字转换为16进制字符串。
  2. UUID.randomUUID().toString(); 生成唯一标识符(UUID)并将其转换为字符串。
  3. RandomStringUtils.randomAlphanumeric(16); 生成长度为16的随机字母数字字符串。
- Manindar
如何在数据维度有限的情况下确保唯一性?如果学生人数超过10^7,您将无法为每个学生分配唯一编号。 - Alex Salauyou
7个回答

132

生成一个随机字符串很容易 - 只需使用 java.util.Random 和一个包含您想要可用的所有字符的字符串,例如:

public static String generateString(Random rng, String characters, int length)
{
    char[] text = new char[length];
    for (int i = 0; i < length; i++)
    {
        text[i] = characters.charAt(rng.nextInt(characters.length()));
    }
    return new String(text);
}

现在,为了保证唯一性,您需要将生成的字符串存储在某个地方。如何存储将取决于您应用程序的其余部分。


3
@chandra: 是的,完全正确。给它一个你想从中选择的字符的字符串。所以如果你只想要数字,你会传入"0123456789"。如果你只想要大写字母,你会传入"ABCDEFGHIJKLMNOPQRSTUVWXYZ"等等。 - Jon Skeet
3
使用UUID.randomUUID().toString()比使用其他方式更正确吗?如果是的话,为什么? - Isaac
3
这句话的意思是:“它可以更好地控制输出,无论是使用哪些字符还是确定字符串的长度。” - Jon Skeet
4
你为什么将随机数作为参数传递? - RockOnGom
2
@RockOnGom:抱歉,我之前错过了这个评论。对于这样的事情,我认为Random实际上是一个依赖项 - 在此接受它允许调用者决定是否使用预先种子化的Random以获得可重复的结果(例如用于测试),或者使用SecureRandom使其适用于安全目的等。 - Jon Skeet
显示剩余4条评论

56

这个链接 http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/RandomStringUtils.html 坏了!!! - Visruth
安全哈希不是用于唯一性,而是用于隐藏初始值。 - Alex Salauyou

18

3
这与“七个随机数字字符的字符串”不同。 - Jon Skeet
随机UUID基本上保证是唯一的。如果您需要从中获得数字字符串,则可以对其进行哈希。 - pedorro

5
Random ran = new Random();
int top = 3;
char data = ' ';
String dat = "";

for (int i=0; i<=top; i++) {
  data = (char)(ran.nextInt(25)+97);
  dat = data + dat;
}

System.out.println(dat);

2
我认为下面的类代码会对你有所帮助。它支持多线程,但你可以进行一些改进,例如删除sync块并将sync应用于getRandomId()方法。
public class RandomNumberGenerator {

private static final Set<String> generatedNumbers = new HashSet<String>();

public RandomNumberGenerator() {
}

public static void main(String[] args) {
    final int maxLength = 7;
    final int maxTry = 10;

    for (int i = 0; i < 10; i++) {
        System.out.println(i + ". studentId=" + RandomNumberGenerator.getRandomId(maxLength, maxTry));
    }
}

public static String getRandomId(final int maxLength, final int maxTry) {
    final Random random = new Random(System.nanoTime());
    final int max = (int) Math.pow(10, maxLength);
    final int maxMin = (int) Math.pow(10, maxLength-1);
    int i = 0;
    boolean unique = false;
    int randomId = -1;
    while (i < maxTry) {
        randomId = random.nextInt(max - maxMin - 1) + maxMin;

        synchronized (generatedNumbers) {
            if (generatedNumbers.contains(randomId) == false) {
                unique = true;
                break;
            }
        }
        i++;
    }
    if (unique == false) {
        throw new RuntimeException("Cannot generate unique id!");
    }

    synchronized (generatedNumbers) {
        generatedNumbers.add(String.valueOf(randomId));
    }

    return String.valueOf(randomId);
}

}

1

你需要先问自己一个问题,你是否真的需要ID是随机的。有时,顺序ID已经足够好了。

现在,如果你确实需要它是随机的,我们首先注意到一个不包含重复数字的生成数列不能被称为随机的。:p 现在我们把这个搞定了,最快的方法是使用一个HashtableHashMap来包含所有已经生成的ID。每当生成一个新的ID时,检查它是否在哈希表中,如果已经存在,则重新生成。如果学生人数远小于ID范围,这通常会很有效。如果不是,你就会陷入更深的麻烦,因为需要重新生成ID的概率会增加,P(生成新ID)=已生成的ID数量/所有可能ID的数量。在这种情况下,请回到第一段(你是否需要ID是随机的?)。

希望这可以帮助到你。


是的,它必须是随机的,这是我的项目规格说明书所说的。 - chandra wibowo

1

许多可能性...

你知道如何随机生成一个整数吧? 因此,你可以从中生成一个字符...(例如65 -> A)

这取决于你需要什么,随机程度,涉及的安全性...但对于学校项目来说,我想获取UUID子字符串就足够了 :)


嗯,这只是一个学校项目,所以我不需要考虑安全等问题。但是UUID生成的字符串有32个字符,我只需要7个字符而已。 哦,我突然有个主意,能不能只取这32个字符中的前7个字符呢? - chandra wibowo
使用子字符串(substring)...就是我说的那样 :) - Sebastien Lorber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接