生成5位永久不重复的序列号?

虐心87 2014-06-10 04:04:43
如何生成5位永久不重复的序列号? 序列号要求由数字或者字母组成(不能使纯数字或者字母)
最近在做生成券,用的随机数方法,还是会重复,请教有什么方法?
...全文
9632 64 打赏 收藏 转发到动态 举报
写回复
用AI写文章
64 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangchao19890805 2014-06-13
  • 打赏
  • 举报
回复
引用 52 楼 zhaopin_0927 的回复:
是的,全部都是AAAAAAAA也不符合要求
符合这种要求的情况应该是P(36,8)=1220096908800

把a-z 0-9 字符放到一个list里,然后用Collections.shuffle取前8个字符。
佐佑不分 2014-06-13
  • 打赏
  • 举报
回复
引用 4 楼 swolf119 的回复:
必须要随机数吗?直接序列排下去不行?
不重复只能这样了貌似
光脚满地跑 2014-06-13
  • 打赏
  • 举报
回复
综合楼上几位大神的回复 数据库建一张表,包含id和valid 插入可能的所有数据(不一定是随机顺序) 然后从数据库中获取随机第N条数据,设置标志位 这样做的好处是速度快,空间占用率也不是特别的大(咕~) 对未来扩展也有好处
tianchanzi201 2014-06-12
  • 打赏
  • 举报
回复
生成判断下是否存在,不可以吗
miracleliu 2014-06-12
  • 打赏
  • 举报
回复
把99999到100000放到数组; 在0~数组size,随机数选一个,选到的就置0;
 public static void main(String[] args) {

        int[] bits = new int[89999];
        for (int i = 0; i < 89999; i++) {
            bits[i] = 10000 + i;
        }
        
        for (int i = 0; i < 11110; i++) {
            System.out.println(getOne(bits));
        }

    }

    private static int getOne(int[] bits) {
        int ret = -1;
        for (int i = 0; i < 89999; i++) {
            Random rd1 = new Random();
            int rad = rd1.nextInt(89999);
            if (bits[rad] != 0) {
                ret = bits[rad];
                bits[rad] = 0;
                break;
            } else {
                System.out.println("collision -" + rad);
            }
        }
        return ret;
    }
shine333 2014-06-12
  • 打赏
  • 举报
回复
引用 59 楼 zhaopin_0927 的回复:
[quote=引用 56 楼 shine333 的回复:] 不用表。你券是第n张,就调用encode(n)
如果第一笔申请生成99999条券,后续再有申请单申请生成券,如何知道第二次生成券号的开始位置?是不是到存券的表中一共生成了多少张券?还有如果1220096908800张券号用完作如何处理?[/quote] 前面已经答复过了
虐心87 2014-06-12
  • 打赏
  • 举报
回复
引用 56 楼 shine333 的回复:
不用表。你券是第n张,就调用encode(n)
如果第一笔申请生成99999条券,后续再有申请单申请生成券,如何知道第二次生成券号的开始位置?是不是到存券的表中一共生成了多少张券?还有如果1220096908800张券号用完作如何处理?
shine333 2014-06-12
  • 打赏
  • 举报
回复
我给你的两段代码,在参数属于[1, MAX]范围内,encode结果唯一。这个靠的是数学,不是数据库
shine333 2014-06-12
  • 打赏
  • 举报
回复
你只要知道这张券是“开天辟地”以来,生成的第几张券。假设你这张券的记录是存在表里面的。 你先生成这样一行券的记录,主键一般是自增/SEQ,你就用这个主键(自增/SEQ的结果)调用一下encode方法,然后更新掉这张券里面,券的号码字段即可。 小提示:避免拿券的号码、身份证、合同号、订单号做主键。无论为了效率上,还是今后业务升级的考虑。
shine333 2014-06-12
  • 打赏
  • 举报
回复
不用表。你券是第n张,就调用encode(n)
虐心87 2014-06-12
  • 打赏
  • 举报
回复
引用 53 楼 shine333 的回复:


  /** 最大值 */
  public static final long MAX = 1220096908800L; // 36*35*34*33*32*31*30*29

  /** 乘法用的素数 */
  public static final long P = 982451653L;

  /** 加法用的素数 */
  public static final long Q = 9007;

  /** 编码长度 */
  public static final int LEN = 8;

  /** 采用36进制 */
  public static final int RADIX = 36;

  /**
   * 编码方法。
   * 
   * @param number
   *          序号
   * @return 8位编码
   * @throws IllegalArgumentException
   *           如果序号超过范围
   */
  public static String encode(long number) {
    if (number <= 0 || number > MAX) {
      throw new IllegalArgumentException();
    }
    long x = (number * P + Q) % MAX;

    return encode0(x);
  }

  private static String encode0(long x) {
    List<Character> list = new LinkedList<Character>();
    for (int i = 0; i < RADIX; i++) {
      list.add(Character.toUpperCase(Character.forDigit(i, RADIX)));
    }

    char[] codes = new char[LEN];
    int radix = RADIX;
    for (int i = LEN; i-- > 0;) {
      int n = (int) (x % radix);
      codes[i] = list.remove(n);
      x /= radix;
      radix--;
    }

    return new String(codes);
  }
非常感谢!请问下,我现在是先把这些券号生成好单独放在一张表中,生成券的时候随机的到表中取券号过来使用,取过的就标志一个状态为已使用吗?还是使用其它的方式?
shine333 2014-06-12
  • 打赏
  • 举报
回复
前20个:

10MOY8NW
01EFWB7L
0234UCRA
02QURE9Z
03GJPETO
0469OICD
16X0LIW2
05LQIKER
069EFLYG
1A06EOI5
18NWCP0U
08DM9RKJ
0E4D9T38
0BS15TLX
0CHR3W5M
0E7H1XPB
1EV6YZ90
1DJVY0RP
0HBMW2AE
1I0CT4U3
shine333 2014-06-12
  • 打赏
  • 举报
回复


  /** 最大值 */
  public static final long MAX = 1220096908800L; // 36*35*34*33*32*31*30*29

  /** 乘法用的素数 */
  public static final long P = 982451653L;

  /** 加法用的素数 */
  public static final long Q = 9007;

  /** 编码长度 */
  public static final int LEN = 8;

  /** 采用36进制 */
  public static final int RADIX = 36;

  /**
   * 编码方法。
   * 
   * @param number
   *          序号
   * @return 8位编码
   * @throws IllegalArgumentException
   *           如果序号超过范围
   */
  public static String encode(long number) {
    if (number <= 0 || number > MAX) {
      throw new IllegalArgumentException();
    }
    long x = (number * P + Q) % MAX;

    return encode0(x);
  }

  private static String encode0(long x) {
    List<Character> list = new LinkedList<Character>();
    for (int i = 0; i < RADIX; i++) {
      list.add(Character.toUpperCase(Character.forDigit(i, RADIX)));
    }

    char[] codes = new char[LEN];
    int radix = RADIX;
    for (int i = LEN; i-- > 0;) {
      int n = (int) (x % radix);
      codes[i] = list.remove(n);
      x /= radix;
      radix--;
    }

    return new String(codes);
  }
虐心87 2014-06-12
  • 打赏
  • 举报
回复
引用 51 楼 shine333 的回复:
也就是 ABCDEFGH可以,但是AACDEFGH就不可以了?
是的,全部都是AAAAAAAA也不符合要求 符合这种要求的情况应该是P(36,8)=1220096908800
shine333 2014-06-12
  • 打赏
  • 举报
回复
也就是 ABCDEFGH可以,但是AACDEFGH就不可以了?
虐心87 2014-06-12
  • 打赏
  • 举报
回复
引用 40 楼 shine333 的回复:
[quote=引用 31 楼 zhaopin_0927 的回复:] 1 5位不重复 2 避免重复
最多准备支持多少张券?如前面回复
引用 32 楼 jmppok 的回复:
36^5 = 60466176 才6000W个, 随机怎能不重复? 所以还是制定一定的规则来推算比较好.
够不够用?够用的话:
 
  /** 最大值 */
  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,且一定是素数。素数表可以去这里[/quote] 不好意思?现在券号生成规则变了,只需要8位随机码就可以了,要求每个字符在生成的8位码里不重复出现
  • 打赏
  • 举报
回复
Set s = new HashSet(); for (int i = 0; s.size() < 1000; i++) { s.add(随机的号码); } 这样可以生成1000个不重复的
shine333 2014-06-11
  • 打赏
  • 举报
回复
所以,你到底是要8位不重复,还是5位不重复的? 到底是为了避免重复,还是为了防伪? 举个例子,身份证确实是不重复的。但是身份证号码第18位,他的目的,不是为了防止重复,而是为了防伪。 比如522528198106150020这个号码和任何其他号码都不重复。但却是一个假的身份证号码。
shine333 2014-06-11
  • 打赏
  • 举报
回复
具体到实际使用,可能因为字体的缘故,可能会避免使用字母I,以免和1混淆。
shine333 2014-06-11
  • 打赏
  • 举报
回复
最初的20个号码:

WW389
LV0GI
AUXNR
ZSUV0
ORR3A
DQOBJ
2PLJS
RNIR1
GMFZA
5LC7K
UJ9FT
JI6N2
8H3VB
XF03L
MEXAU
BDUI3
0CRQC
PAOYL
E9L6V
38IE4
加载更多回复(44)

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧