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

2023年6月5日09:07:18

琢磨了一晚上,就为了写一个“不重复的随机码生成函数”,生成格式包含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的更多交流,请给我留言,简单的问题,也可以很复杂化,只有更深入的去尝试,才能更深刻的理解每一个细节问题。

  • 作者:公司扫地僧
  • 原文链接:https://blog.csdn.net/laotoumo/article/details/50334289
    更新时间:2023年6月5日09:07:18 ,共 1941 字。