生成5位永久不重复的序列号? 验证码java算法随机数 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你好,我们现在这个是按照批次生成的,一个批次有很多券,券是15位的,前10位是有规律的,后5位是随机的,我们使用的时候是用后5位来确定某一张券的,我们现在既要保证这个券在本批次不重复,还要在其他批次也不重复,难道要生成前到数据库中先查一遍? 自己构建 一个HashMap,把生成的数据丢进去做唯一检查如果内存不够用,调大,如果还是不够,就上缓存服务器,如果没有条件用缓存服务器,就用数据库 就是长周期随机数生成嘛,这个不是很难吧建议看看这篇文章 “产生伪随机数常用的两种算法”直接用glibc随机数的方法就应该可以满足你的要求,它的循环周期是2^n,n是0~32的整数,比如下面的例子,可以产生不重复的0 ~ 2^28-1(268435455)之间的数 public static int nextRand(int n) { return (1103515245 * n + 12345) & 0x0FFFFFFF; } 只是五位而已,就算查找也很快啊。百万级的自然有算法可以做到比如,bloom filter 这样的检查 set intersection 的东西 建立一个list将所有可能的5位组合放进去。建立随机数,每次从list中取随机数未知的内容,取出后将内容移出list。 可不可以这样:先将序列号生成,保存到数据库中,表中设置一个布尔类型标志位,用过的是true,没用过的是false;需要时检索出10个没用过的序列号(标志位:false),随机抽出一个分配给客户,再将标志位设置true。这样的话即不会重复,性能也差不到哪去。 我不清楚我的方法 效率怎么样,但是可以建立一张只有主键的表,里面把35^5 几千万条数据存进去,吧count 放入缓存,每次用random 取随机行号,取出数据的操作之后立马执行删除操作 随即进行count数量减少这样可以保证你在几千万数据用完之前不会重复 个人建议: 一次性生成 N张券(或者 N个 5位 String 串,保证不重复), 可以用多个表 存储,或者 多个 list 存储 (具体看 数据量有多大),然后 对用户所谓的 “生成” 其实 就是从这些 已经 生成好的数据中 随即的 取一个 ,然后在吧该数据 从存储数据的地方删除。 最多准备支持多少张券?如前面回复够不够用?够用的话: /** 最大值 */ public static final long MAX = 60466176; // 36 ^ 6 /** 乘法用的素数 */ public static final long P = 15485857; /** 加法用的素数 */ public static final long Q = 9007; /** 编码长度 */ public static final int LEN = 5; /** 采用36进制 */ public static final int RADIX = 36; /** * 编码方法。 * * @param number * 序号 * @return 5位编码 * @throws IllegalArgumentException * 如果序号超过范围 */ public static String encode(int number) { if (number <= 0 || number > MAX) { throw new IllegalArgumentException(); } long x = ((long) number * P + Q) % MAX; char[] codes = new char[LEN]; Arrays.fill(codes, '0'); String str = Long.toString(x, RADIX); System.arraycopy(str.toCharArray(), 0, codes, LEN - str.length(), str.length()); reverse(codes); return new String(codes).toUpperCase(); } private static void reverse(char[] codes) { for (int i = LEN >> 1; i-- > 0;) { codes[i] ^= codes[LEN - i - 1]; codes[LEN - i - 1] ^= codes[i]; codes[i] ^= codes[LEN - i - 1]; } }此过程,“理论上”可逆,但是decode算法实际上没法用——太慢,几乎等同于把所有可能的值再去encode一遍做比较。其中P越大,产生的编码越“随机”,但是请确保P*MAX小于Long.MAX_VALUE,且一定是素数。素数表可以去这里 最初的20个号码:WW389LV0GIAUXNRZSUV0ORR3ADQOBJ2PLJSRNIR1GMFZA5LC7KUJ9FTJI6N28H3VBXF03LMEXAUBDUI30CRQCPAOYLE9L6V38IE4 Set s = new HashSet();for (int i = 0; s.size() < 1000; i++) { s.add(随机的号码);}这样可以生成1000个不重复的 最多准备支持多少张券?如前面回复够不够用?够用的话: /** 最大值 */ public static final long MAX = 60466176; // 36 ^ 6 /** 乘法用的素数 */ public static final long P = 15485857; /** 加法用的素数 */ public static final long Q = 9007; /** 编码长度 */ public static final int LEN = 5; /** 采用36进制 */ public static final int RADIX = 36; /** * 编码方法。 * * @param number * 序号 * @return 5位编码 * @throws IllegalArgumentException * 如果序号超过范围 */ public static String encode(int number) { if (number <= 0 || number > MAX) { throw new IllegalArgumentException(); } long x = ((long) number * P + Q) % MAX; char[] codes = new char[LEN]; Arrays.fill(codes, '0'); String str = Long.toString(x, RADIX); System.arraycopy(str.toCharArray(), 0, codes, LEN - str.length(), str.length()); reverse(codes); return new String(codes).toUpperCase(); } private static void reverse(char[] codes) { for (int i = LEN >> 1; i-- > 0;) { codes[i] ^= codes[LEN - i - 1]; codes[LEN - i - 1] ^= codes[i]; codes[i] ^= codes[LEN - i - 1]; } }此过程,“理论上”可逆,但是decode算法实际上没法用——太慢,几乎等同于把所有可能的值再去encode一遍做比较。其中P越大,产生的编码越“随机”,但是请确保P*MAX小于Long.MAX_VALUE,且一定是素数。素数表可以去这里不好意思?现在券号生成规则变了,只需要8位随机码就可以了,要求每个字符在生成的8位码里不重复出现 ssh2整合 字符串提取关键字显示问题!急! Struts2类库上载,但myeclipse仍旧无法识别 如何在EJB里进行Http链接 请问一个以WEBLOGIC为应用服务器在JSP中使用CSS如何部署的问题. -----》『提问』Hibernate 的查询问题,焦急等待 最近中兴通讯的全国招聘会一天面试结束后,下面还有没有面试?下面会干什么? struts2防表单提交问题 求助IO流这块的一个demo里面的问题 @提到我功能源码解析--java tomcat的AJP端口问题 用Xshell运行jar包出现无法建立数据源连接的问题
如果内存不够用,调大,如果还是不够,就上缓存服务器,如果没有条件用缓存服务器,就用数据库
建议看看这篇文章 “产生伪随机数常用的两种算法”直接用glibc随机数的方法就应该可以满足你的要求,它的循环周期是2^n,n是0~32的整数,比如下面的例子,可以产生不重复的0 ~ 2^28-1(268435455)之间的数
public static int nextRand(int n) {
return (1103515245 * n + 12345) & 0x0FFFFFFF;
}
先将序列号生成,保存到数据库中,表中设置一个布尔类型标志位,用过的是true,没用过的是false;
需要时检索出10个没用过的序列号(标志位:false),随机抽出一个分配给客户,再将标志位设置true。
这样的话即不会重复,性能也差不到哪去。
里面把35^5 几千万条数据存进去,吧count 放入缓存,每次用random 取随机行号,
取出数据的操作之后立马执行删除操作 随即进行count数量减少
这样可以保证你在几千万数据用完之前不会重复
够不够用?够用的话:
/** 最大值 */
public static final long MAX = 60466176; // 36 ^ 6 /** 乘法用的素数 */
public static final long P = 15485857;
/** 加法用的素数 */
public static final long Q = 9007; /** 编码长度 */
public static final int LEN = 5; /** 采用36进制 */
public static final int RADIX = 36; /**
* 编码方法。
*
* @param number
* 序号
* @return 5位编码
* @throws IllegalArgumentException
* 如果序号超过范围
*/
public static String encode(int number) {
if (number <= 0 || number > MAX) {
throw new IllegalArgumentException();
}
long x = ((long) number * P + Q) % MAX;
char[] codes = new char[LEN];
Arrays.fill(codes, '0');
String str = Long.toString(x, RADIX);
System.arraycopy(str.toCharArray(),
0,
codes,
LEN - str.length(),
str.length());
reverse(codes);
return new String(codes).toUpperCase();
} private static void reverse(char[] codes) {
for (int i = LEN >> 1; i-- > 0;) {
codes[i] ^= codes[LEN - i - 1];
codes[LEN - i - 1] ^= codes[i];
codes[i] ^= codes[LEN - i - 1];
}
}此过程,“理论上”可逆,但是decode算法实际上没法用——太慢,几乎等同于把所有可能的值再去encode一遍做比较。
其中P越大,产生的编码越“随机”,但是请确保P*MAX小于Long.MAX_VALUE,且一定是素数。素数表可以去这里
LV0GI
AUXNR
ZSUV0
ORR3A
DQOBJ
2PLJS
RNIR1
GMFZA
5LC7K
UJ9FT
JI6N2
8H3VB
XF03L
MEXAU
BDUI3
0CRQC
PAOYL
E9L6V
38IE4
for (int i = 0; s.size() < 1000; i++) {
s.add(随机的号码);
}这样可以生成1000个不重复的
够不够用?够用的话:
/** 最大值 */
public static final long MAX = 60466176; // 36 ^ 6 /** 乘法用的素数 */
public static final long P = 15485857;
/** 加法用的素数 */
public static final long Q = 9007; /** 编码长度 */
public static final int LEN = 5; /** 采用36进制 */
public static final int RADIX = 36; /**
* 编码方法。
*
* @param number
* 序号
* @return 5位编码
* @throws IllegalArgumentException
* 如果序号超过范围
*/
public static String encode(int number) {
if (number <= 0 || number > MAX) {
throw new IllegalArgumentException();
}
long x = ((long) number * P + Q) % MAX;
char[] codes = new char[LEN];
Arrays.fill(codes, '0');
String str = Long.toString(x, RADIX);
System.arraycopy(str.toCharArray(),
0,
codes,
LEN - str.length(),
str.length());
reverse(codes);
return new String(codes).toUpperCase();
} private static void reverse(char[] codes) {
for (int i = LEN >> 1; i-- > 0;) {
codes[i] ^= codes[LEN - i - 1];
codes[LEN - i - 1] ^= codes[i];
codes[i] ^= codes[LEN - i - 1];
}
}此过程,“理论上”可逆,但是decode算法实际上没法用——太慢,几乎等同于把所有可能的值再去encode一遍做比较。
其中P越大,产生的编码越“随机”,但是请确保P*MAX小于Long.MAX_VALUE,且一定是素数。素数表可以去这里
不好意思?现在券号生成规则变了,只需要8位随机码就可以了,要求每个字符在生成的8位码里不重复出现