您的位置:首页 > 编程语言 > Java开发

JAVA生成指定位数不重复的随机数,随机数含0-9、A-Z

2015-12-16 23:20 429 查看
琢磨了一晚上,就为了写一个“不重复的随机码生成函数”,生成格式包含0-9,a-z。

头脑风暴,异想天开,写下了如下算法,看上去很高大上的一个随机生成方法。

原理先产生一个UUID,再根据UUID生成一个随机数,UUID,不重复嘛。一测试,坑爹了,生成100万条长度为4的随机码,重复率达到25%,傻眼了。

/**
* 随机码生成
* @author Mo
*
* @param length 随机码长度
* @return
*/
public static String random1(int length){
/*
* 这里直接数字代替,没用uuid.length()
* */
String uuid = UUID.randomUUID().toString().replace("-", "");

int len = uuid.length();

/*定义随机码字符串变量,初始化为""*/
String random = "";

/*
* 循环截取UUID
* len/length 每次循环截取的字符串长度
* len%length 如果出现32长度除不尽的情况,取余数
* */
int subLen = len/length;
int remainder = len%length;

/*定义substring的两个参数*/
int start = 0,end = 0;
for(int i=0;i<length;i++){
/*
* 计算start和end的值
* 这里涉及两种方法,一种是除不尽的时候,将截取长度分散到头部,一种是分散到尾部
*
* uuid的前部分是时间戳构成的,因此前部分截取越少,重复率越底
* 固本方法采用了将多余的部分分散到尾部
* */
/*分散到尾部,如length为7的时候4,4,4,4,5,5,5*/
//			end = start + (length-i <= remainder ? 1 : 0)+subLen;
/*分散到头部,如length为7 的时候5,5,5,5,4,4,4*/
end = start + (i < remainder ? 1 : 0)+subLen;
/*截取到的字符串*/
String code = uuid.substring(start,end);
/*对所截取的长度进行16位求和*/
int count = 0;
for(char c : code.toCharArray()){
count += Integer.valueOf(String.valueOf(c),16);
}
/*将求和结果转化成36位,并增加到随机码中,36位包含了0-9a-z*/
random += Integer.toString(count%36, 36);
start = end;
}
/*返回随机码*/
return random;
}

泡杯咖啡,清醒一下,随机码生成函数2应运而生,小学生(入门级程序员)都能看懂。经过测试,生成100万条长度4的随机码,重复率也在25%左右。

推荐方法:

/**
* 随机码生成
* @author Mo
*
* @param length
* @return
*/
public static String random2(int length){
String random = "";
/*随机数函数*/
java.util.Random r=new java.util.Random();
for(int i = 0;i<length;i++){
/*生成36以内的随机数,不含36,并转化为36位*/
random += Integer.toString(r.nextInt(36), 36);
}
return random;
}

事实证明,最复杂的方法并不是最好的方法,程序开发跟其他的事情一样,不要画蛇添足,时间浪费了,性能浪费了,还得不到好的结果。当然,多尝试是对的。

事后想想,既然是随机生成,又要控制长度,长度为4,又怎么会出现不重复的数字呢。当然,将长度调整到8的时候,重复率基本没有,这个没有也不能绝对,只是说概率降低了而已。

总结:要生成不重复的随机码,必经要经过数据验证,拿新生成的随机码去与历史生成数据对比,如果已存在,则舍弃重新生成。如果对长度没要求,可以直接采用UUID,UUID是国际通用的不重复的串,不过长度达到了36位之多。

以下提供一个自写随机码测试函数:

public static void main(String args []){
Set<String> set = new HashSet<String>();
int times = 1000000;
for(int i = 0 ;i<times;i++){
String random = random1(8);
set.add(random);
}
System.out.println("重复了:"+(times-set.size())+"次");
}

关于java的更多交流,请给我留言,简单的问题,也可以很复杂化,只有更深入的去尝试,才能更深刻的理解每一个细节问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java