英文:
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<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;
}
}
答案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<String> numbers = Arrays.asList("1234acb", "djnjwd222", "djwnqfe456");
boolean unique = false;
// Generate the List of string each having only one char from a-z 0-9
List<String> list = "abcdefghijklmnopqrstuvwxyz0123456789".chars()
.mapToObj(c -> 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 ? "Unique" : "Not unique");
}
}
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<String> numbers = Arrays.asList("1234acb", "djnjwd222", "djwnqfe456");
boolean unique = false;
// Generate the List of string each having only one char from a-z 0-9
List<String> list = "abcdefghijklmnopqrstuvwxyz0123456789".chars()
.mapToObj(c -> 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("", list.subList(0, 16));
System.out.println(str);
// Check if `numbers` contains `str`
if (!numbers.contains(str)) {
unique = true;
}
System.out.println(unique ? "Unique" : "Not unique");
}
}
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("-", "").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<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()));
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 <- another answer
191 <- this answer
EDIT:
I just tested this answer with UUID.randomUUID().toString().replace("-", "").substring(0, 16)
and it turns out that this answer is faster than UUID.randomUUID().toString().replace("-", "").substring(0, 16)
using Set<String>
as backing data type. Here is it's pastebin.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论