我一直在寻找一种简单的Java算法来生成伪随机字母数字字符串。在我的情况下,它将被用作唯一的会话/密钥标识符,“很可能”在超过50万代的时间内是唯一的(我的需求实际上不需要更复杂的东西)。

理想情况下,我可以根据我的独特性需求指定长度。例如,生成的长度为12的字符串可能看起来像“AEYGF7K0DM1X”。


当前回答

令人惊讶的是,这里没有人建议,但:

import java.util.UUID

UUID.randomUUID().toString();

容易的

这样做的好处是UUID很好、很长,并且保证几乎不可能发生冲突。

维基百科对此有很好的解释:

“……只有在未来100年内每秒生成10亿个UUID之后,仅创建一个重复的概率才会达到50%。”

前四位是版本类型,两位是变体,因此您可以得到122位随机数。因此,如果需要,可以从末尾截断以减小UUID的大小。这是不推荐的,但你仍然有大量的随机性,足以让你的500k记录变得容易。

其他回答

我找到了生成随机十六进制编码字符串的解决方案。所提供的单元测试似乎符合我的主要用例。虽然,它比提供的一些其他答案稍微复杂一些。

/**
 * 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);
        }
    }
}
import java.util.Random;

public class passGen{
    // Version 1.0
    private static final String dCase = "abcdefghijklmnopqrstuvwxyz";
    private static final String uCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String sChar = "!@#$%^&*";
    private static final String intChar = "0123456789";
    private static Random r = new Random();
    private static StringBuilder pass = new StringBuilder();

    public static void main (String[] args) {
        System.out.println ("Generating pass...");
        while (pass.length () != 16){
            int rPick = r.nextInt(4);
            if (rPick == 0){
                int spot = r.nextInt(26);
                pass.append(dCase.charAt(spot));
            } else if (rPick == 1) {
                int spot = r.nextInt(26);
                pass.append(uCase.charAt(spot));
            } else if (rPick == 2) {
                int spot = r.nextInt(8);
                pass.append(sChar.charAt(spot));
            } else {
                int spot = r.nextInt(10);
                pass.append(intChar.charAt(spot));
            }
        }
        System.out.println ("Generated Pass: " + pass.toString());
    }
}

这只是将密码添加到字符串中。。。是的,效果很好。过来看。。。这很简单;我写的。

在前面的答案中有很多StringBuilder的用法。我想这很简单,但它需要每个字符调用一个函数,增加一个数组,等等。。。

如果使用字符串生成器,建议指定字符串所需的容量,即。,

new StringBuilder(int capacity);

这是一个不使用StringBuilder或字符串附加的版本,也没有字典。

public static String randomString(int length)
{
    SecureRandom random = new SecureRandom();
    char[] chars = new char[length];
    for(int i=0; i<chars.length; i++)
    {
        int v = random.nextInt(10 + 26 + 26);
        char c;
        if (v < 10)
        {
            c = (char)('0' + v);
        }
        else if (v < 36)
        {
            c = (char)('a' - 10 + v);
        }
        else
        {
            c = (char)('A' - 36 + v);
        }
        chars[i] = c;
    }
    return new String(chars);
}

令人惊讶的是,这里没有人建议,但:

import java.util.UUID

UUID.randomUUID().toString();

容易的

这样做的好处是UUID很好、很长,并且保证几乎不可能发生冲突。

维基百科对此有很好的解释:

“……只有在未来100年内每秒生成10亿个UUID之后,仅创建一个重复的概率才会达到50%。”

前四位是版本类型,两位是变体,因此您可以得到122位随机数。因此,如果需要,可以从末尾截断以减小UUID的大小。这是不推荐的,但你仍然有大量的随机性,足以让你的500k记录变得容易。

给定一些字符(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));
  }
}

在沙盒上试试另请参阅其他语言实现随机字符串生成器