生成不在列表中的字母数字的高效方法

huangapple go评论65阅读模式
英文:

Efficient way to generate alphanumeric number which is not already in list

问题

这是我的代码,是否有比这更有效的方法?

List<String> numbers = Arrays.asList("1234acb", "djnjwd222", "djwnqfe456");
boolean unique = false;
while (!unique) {
    final String ALPHA_NUMERIC = "abcdefghijklmnopqrstuvwxyz0123456789";
    StringBuilder builder = new StringBuilder();
    int length = 15;
    while (length-- != 0) {
        int character = (int) (Math.random() * ALPHA_NUMERIC.length());
        builder.append(ALPHA_NUMERIC.charAt(character));
    }
    if (!numbers.contains(builder.toString())) {
        unique = true;
    }
}
英文:

This is my code is there any efficient way other than this

        List&lt;String&gt; numbers = Arrays.asList(&quot;1234acb&quot;,&quot;djnjwd222&quot;,&quot;djwnqfe456&quot;);
        boolean unique = false;
        while(!unique){
            final String ALPHA_NUMERIC = &quot;abcdefghijklmnopqrstuvwxyz0123456789&quot;;
            StringBuilder builder = new StringBuilder();
            int length = 15;
            while (length-- != 0) {
                int character = (int)(Math.random()*ALPHA_NUMERIC.length());
                builder.append(ALPHA_NUMERIC.charAt(character));
            }
            if(!numbers.contains(builder.toString())){
                unique = true;
            }
        }

答案1

得分: 1

Yet another update

感谢 Joni 对我上次更新的审查。他正确地指出了上次更新中的代码可能只使用了一个符号。以下解决方案解决了这个问题。它还以改进的方式处理了唯一性。

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> numbers = Arrays.asList("1234acb", "djnjwd222", "djwnqfe456");
        boolean unique = false;

        // 生成只包含 a-z 和 0-9 的每个字符的字符串列表
        List<String> list = "abcdefghijklmnopqrstuvwxyz0123456789".chars()
                                .mapToObj(c -> String.valueOf((char) c))
                                .collect(Collectors.toList());

        // 打乱列表的元素
        Collections.shuffle(list);

        // 从 JVM 获取纳秒
        long nano = System.nanoTime();
        StringBuilder str = new StringBuilder();
        while (nano != 0) {
            // 从 `list` 中获取索引为 `nano` 的最后一位数字的字符串(字符)
            str.append(list.get((int) (nano % 10)));

            // 将 `nano` 缩小十分之一
            nano /= 10;
        }

        System.out.println(str);

        // 检查 `numbers` 是否包含 `str`
        if (!numbers.contains(str)) {
            unique = true;
        }

        System.out.println(unique ? "Unique" : "Not unique");
    }
}

一个示例运行:

a5ago6u393g6frf
Unique

更新

正如 Joni 指出的那样,原始答案中生成的字符串仅包含 0-9 a-f。以下解决方案解决了这个问题。

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> numbers = Arrays.asList("1234acb", "djnjwd222", "djwnqfe456");
        boolean unique = false;

        // 生成只包含 a-z 和 0-9 的每个字符的字符串列表
        List<String> list = "abcdefghijklmnopqrstuvwxyz0123456789".chars()
                                .mapToObj(c -> String.valueOf((char) c))
                                .collect(Collectors.toList());

        // 打乱列表的元素
        Collections.shuffle(list);

        // 通过连接列表的前 16 个元素来获取一个字符串
        String str = String.join("", list.subList(0, 16));
        System.out.println(str);

        // 检查 `numbers` 是否包含 `str`
        if (!numbers.contains(str)) {
            unique = true;
        }

        System.out.println(unique ? "Unique" : "Not unique");
    }
}

一个示例运行:

miblz0o61r89xdg5
Unique

原始答案:

您可以使用 UUID 生成一个随机的字母数字字符串。请注意,这个字符串包含 -,您可以将其替换为空字符串,然后从结果字符串中获取前 16 个字符。

import java.util.UUID;

public class Main {
    public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString().replace("-", "").substring(0, 16));
    }
}

输出:

68477a8bf3084a42
英文:

Yet another update

Thanks to Joni for reviewing my last update. He rightly pointed out that the code in the last update could use a symbol only once. The following solution solves that issue. It also handles the uniqueness in an improved way.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
	public static void main(String[] args) {
		List&lt;String&gt; numbers = Arrays.asList(&quot;1234acb&quot;, &quot;djnjwd222&quot;, &quot;djwnqfe456&quot;);
		boolean unique = false;

		// Generate the List of string each having only one char from a-z 0-9
		List&lt;String&gt; list = &quot;abcdefghijklmnopqrstuvwxyz0123456789&quot;.chars()
								.mapToObj(c -&gt; String.valueOf((char) c))
								.collect(Collectors.toList());

		// Shuffle the elements of the list
		Collections.shuffle(list);

		//Get nano seconds from JVM
		long nano = System.nanoTime();
		StringBuilder str = new StringBuilder();
		while (nano != 0) {
			// Get the string (char) from `list` at the index = last digit of `nano`
			str.append(list.get((int) (nano % 10)));

			// Make nano smaller by one tenth
			nano /= 10;
		}

		System.out.println(str);

		// Check if `numbers` contains `str`
		if (!numbers.contains(str)) {
			unique = true;
		}

		System.out.println(unique ? &quot;Unique&quot; : &quot;Not unique&quot;);
	}
}

A sample run:

a5ago6u393g6frf
Unique

Update

As pointed out by Joni, the generated string in the original answer contained only 0-9 a-f. The following solution solves that issue:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
	public static void main(String[] args) {
		List&lt;String&gt; numbers = Arrays.asList(&quot;1234acb&quot;, &quot;djnjwd222&quot;, &quot;djwnqfe456&quot;);
		boolean unique = false;

		// Generate the List of string each having only one char from a-z 0-9
		List&lt;String&gt; list = &quot;abcdefghijklmnopqrstuvwxyz0123456789&quot;.chars()
								.mapToObj(c -&gt; String.valueOf((char) c))
								.collect(Collectors.toList());

		// Shuffle the elements of the list
		Collections.shuffle(list);

		// Get a string by joining the first 16 elements of the list
		String str = String.join(&quot;&quot;, list.subList(0, 16));
		System.out.println(str);
		
		// Check if `numbers` contains `str`
		if (!numbers.contains(str)) {
			unique = true;
		}

		System.out.println(unique ? &quot;Unique&quot; : &quot;Not unique&quot;);
	}
}

A sample run:

miblz0o61r89xdg5
Unique

Original answer:

You can use UUID to generate a random alphanumeric string. Note that this string contains - which you can replace with an empty string and then get the first 16 characters from the resulting string.

import java.util.UUID;

public class Main {
	public static void main(String[] args) {
		System.out.println(UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;).substring(0, 16));
	}
}

Output:

68477a8bf3084a42

答案2

得分: 1

复制粘贴@AniketSahrawat在版主清理该部分之前的评论。原始帖子可在pastebin上找到,用户Aniket的评论曾在此处可用:

Set<String> numbers = new HashSet<>();
while (!numbers.add(ThreadLocalRandom.current().ints()
    .flatMap(l -> Integer.toString(l, 36).chars())
    .limit(15)
    .collect(StringBuilder::new,
        StringBuilder::appendCodePoint,
        StringBuilder::append).toString()));

如果Aniket决定发布这个答案,我将很高兴删除这个答案。Arvind与Aniket的另一个答案中的性能差异如下:

59968 <- 另一个答案
191   <- 这个答案

编辑:

我刚刚使用UUID.randomUUID().toString().replace("-", "").substring(0, 16)测试了这个答案,结果发现这个答案比使用Set<String>作为支持数据类型的UUID.randomUUID().toString().replace("-", "").substring(0, 16)更快。这是它的pastebin链接。

英文:

Copy pasting @AniketSahrawat's comment before mods clear up the section. The original post is available on pastebin and the comment by user Aniket is/was available here:

Set&lt;String&gt; numbers = new HashSet&lt;&gt;();
while (!numbers.add(ThreadLocalRandom.current().ints()
    .flatMap(l -&gt; Integer.toString(l, 36).chars())
    .limit(15)
    .collect(StringBuilder::new,
        StringBuilder::appendCodePoint,
        StringBuilder::append).toString()));

I would be happy to delete this answer if Aniket decides to post it. Performance difference in another answer by Arvind vs Aniket is:

59968 &lt;- another answer
191   &lt;- this answer

EDIT:

I just tested this answer with UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;).substring(0, 16) and it turns out that this answer is faster than UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;).substring(0, 16) using Set&lt;String&gt; as backing data type. Here is it's pastebin.

huangapple
  • 本文由 发表于 2020年8月9日 21:08:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63326710.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定