【问题标题】:Java: Randomly generate distinct namesJava:随机生成不同的名称
【发布时间】:2011-02-17 06:12:41
【问题描述】:

我需要在 Java 中生成 10,000 个唯一标识符。标识符应该是数字和字母的混合,每个字符少于 10 个。有任何想法吗?内置库将是一个额外的优势。

【问题讨论】:

    标签: java random unique


    【解决方案1】:

    我很晚才回答这个问题,但这对新读者来说真的很有用。 这是获取随机有效名称的一种非常简单有效的方法。 为此,请在 POM.xml 中添加 maven 存储库

    <dependency>
        <groupId>com.github.javafaker</groupId>
        <artifactId>javafaker</artifactId>
        <version>0.12</version>
    </dependency>
    

    然后在你的 Java 代码中使用下面的 Faker 类

    Faker faker = new Faker();
    
    String name = faker.name().fullName();
    String firstName = faker.name().firstName();
    String lastName = faker.name().lastName();
    
    String streetAddress = faker.address().streetAddress();
    

    尝试使用标准 System.out.println(); 打印结果

    更多参考Faker Lib

    【讨论】:

    • 这是金子。谢谢!
    • 超级库。最佳
    • 按照 OP 的要求,不保证唯一性。
    【解决方案2】:
    // class variable
    final String lexicon = "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345674890";
    
    final java.util.Random rand = new java.util.Random();
    
    // consider using a Map<String,Boolean> to say whether the identifier is being used or not 
    final Set<String> identifiers = new HashSet<String>();
    
    public String randomIdentifier() {
        StringBuilder builder = new StringBuilder();
        while(builder.toString().length() == 0) {
            int length = rand.nextInt(5)+5;
            for(int i = 0; i < length; i++) {
                builder.append(lexicon.charAt(rand.nextInt(lexicon.length())));
            }
            if(identifiers.contains(builder.toString())) {
                builder = new StringBuilder();
            }
        }
        return builder.toString();
    }
    

    【讨论】:

    • 为什么类变量不是私有的?它们真的需要成为包范围吗?
    • 不,他们真的没有。上面的示例仅用于算法目的。我希望任何使用它的人都不要复制和粘贴它,而是将说明的概念应用到他们的解决方案中。
    • “if(identifiers.contains(builder.toString())”中缺少 ) 并且程序在语法上是错误的。我会自己更正,但编辑需要至少 6 个字符的修改:)
    • @MSX 谢谢 - 下次我会说只是做一些其他的小改动,并明确你在修复什么。 =) 希望我能给你编辑的代表点... :(
    【解决方案3】:

    为什么不使用 java.util.UUID? 它保证生成唯一标识符,并且它是标准的:-)。

    【讨论】:

      【解决方案4】:

      如果您允许 Apache Commons 语言...

      public String[] getRandomlyNames(final int characterLength, final int generateSize) {
          HashSet<String> list = new HashSet<String>();
          for (int i = 0; i < generateSize; ++i) {
              String name = null;
              do {
                  name = org.apache.commons.lang.RandomStringUtils.randomAlphanumeric(
                          org.apache.commons.lang.math.RandomUtils.nextInt(characterLength - 1) + 1);
              while(list.contains(name));
              list.add(name);
          }
          return list.toArray(new String[]{});
      }
      

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题,但我需要一个任意长的字符串。我想出了这个单行,不需要外部库,它会给你 10 个字符:

        BigInteger.probablePrime(50, new Random()).toString(Character.MAX_RADIX)
        

        长度可以改变,每个字符大约需要 5 位。所做的是过滤和限制长度如下(小写字母,大小为 10):

        BigInteger.probablePrime(100, new Random()).
            toString(Character.MAX_RADIX).
            replaceAll("[0-9]", "").
            substring(0, 10) 
        

        缺点:有点慢。

        【讨论】:

          【解决方案6】:

          您可以尝试获取当前时间的 md5 哈希值,您将得到“随机”标识符作为数字和字母的混合

          【讨论】:

          • 当你在同一时间间隔内执行两次时会发生什么(纳米甚至毫秒都不会更新那么快......)
          • 或者只是从随机初始数字中迭代超过 10000 个数字
          • 这真的很整洁。可能比您需要的计算多一点,但它只是几行代码。
          • Random random = new Random(); for (int i=0; i&lt;10000; i++) { System.out.println(Long.toHexString(random.nextLong())); }
          【解决方案7】:

          最简单最快的方法是生成某个字符串的permutations。只要字符串足够长,您就可以轻松拥有 10,000 个唯一排列。生成排列的好处是您不必担心重复。如果一个字符串包含所有不同的字符,它可以生成 n!排列(n 是字符串的长度)。所以一个包含 8 个不同字符的字符串可以生成 40,320 种不同的排列。

          网上有很多代码可以生成字符串的排列,比如这个http://introcs.cs.princeton.edu/23recursion/Permutations.java.html

          如果希望它们更随机,可以使用不同的字符串作为种子,例如“abcde123”、“efgh456”等。

          【讨论】:

            【解决方案8】:

            你可以试试

            Random rand = new Random();
            Set<String> words = new HashSet<String>();
            while(words.size() < 10000) 
                words.add(Long.toString(Math.abs(rand.nextLong() % 3656158440062976L), 36)));
            

            long 常量只够 10 位,基数为 36 的数字。

            【讨论】:

              猜你喜欢
              • 2013-01-19
              • 2015-03-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-10-16
              • 1970-01-01
              • 1970-01-01
              • 2020-10-16
              相关资源
              最近更新 更多