简体   繁体   中英

Generating a non-repeating list of alpha-numeric codes

I'm trying to generate a list of non-repeating alpha-numeric codes. They will be generated in batches and in volumes such that it won't be feasible to explicitly look at what has been generated before - ie uniqueness needs to be somehow guaranteed without recourse to previous codes outside the current batch.

The codes should have a length of 8 characters with the constraint that certain characters cannot appear in the code (eg l and L) since a user will be re-entering these at a later date.

I'll probably implement this in Java, but I'd appreciate any algorithms or tricks anyone can think of for solving this...

Regards,

Just take System.currentTimeMillis and encode it alphanumerically by mapping each digit to a letter. Keep track of the last one issued (to guard againts multiple generations in the same millisecond) and handle accordingly.

You could just encode an atomic counter such as

AtomicInteger counter = new AtomicInteger();

public String generateId() {
   return Integer.toHexString(counter.getAndIncrement());
}

This will give you 4 billion unique ids.

If you need more than 4 billion, you can use an AtomicLong and use your own encoding for that number depending on which characters you want to allow.

The problem as stated has the obvious solution, which is to generate the codes sequentially starting from zero. Think of each code as a number in base-34 (the digits being 0-9 and AZ except I and L ). If this is not what you want you might like to clarify the question (eg do you want randomness?)

edit : This of course requires you to remember the last code you generated, and carry this one piece of information across batches.

8 nested loops solve your problem trivially. Moreover if you want you can use Random to generate next token and store all tokens in Set. Every time you get new token check whether it is already in set.

Too bad you're constrained to 8 characters. Otherwise, you could have used the MD5 class to generate unique codes.

Anyway, if you want to ensure your codes will be unique, you can encode the generation date in some of your code characters to ensure it won't conflict with previous codes.

For instance, your code would have the form YMDXXXXX , where:

  • Y is the year since 2010 (start with 0, and start using letters when you run out of numbers in 2020)
  • M is the month (same criteria)
  • D is the day (won't be larger than 31, so chars 0-9A-Z should be enough)
  • X are the codes generated on your current batch.

Can you iterate forward like this?

000000a1 000000a2 000000a3 ... 000000ay 000000az 000000b0

Then just remember the last number and all future numbers will be greater than the last one

You may find this useful

long l = 20492;
String s = "wogjz";
s = Long.toString(l, 26+10-2).replace('I','Y').replace('L','Z') // convert long number to string (with letters)
l = Long.parseLong(s.replace('Y','I').replace('Z','L'), 26+10-2) + 1) // Convert string to number

The number 26+10-2 is number of letters plus number of digits minus number of forbidden letters (I and L). The I/Y and Z/L conversion is to use the last letters of the alphabet in cooperation with the Java Library.

You will want to make sure the user does not enter I or L by yourself because my code will not work right otherwise.

You will want to add leading zeros to the string until it reaches 8 characters

Also my program does not know the difference between big and small letters. If you need that then the app would have to be more complex because we would need an array instead of just one long number.

Check this logic. You can exclude any alphabet or number in loop. For your question of 'L', you can exclude as follows

        if(brokenCode[i] == 'K') brokenCode[i] = 'L'; 
        brokenCode[i] = (char)(((int)brokenCode[i]) + 1);

Sample code

class Rextester
{  
    public static void main(String args[])
    {
        String currCode = "00000000";
        for(int i=0; i<2000; i++)
        {
            System.out.println(currCode);
            currCode = getNextCode(currCode);
        }
    }

    private static String getNextCode(String currCode)
    {
        char [] brokenCode;
        brokenCode = currCode.toCharArray();
        for(int i=brokenCode.length-1; i>= 0; i--)
        {
            if(brokenCode[i] == '9')
            {
                brokenCode[i] = 'A';
                break;
            }
            if(brokenCode[i] == 'Z'){
                brokenCode[i] = '0';
                continue;
            }
            brokenCode[i] = (char)(((int)brokenCode[i]) + 1);
            break;
        }
        currCode = new String(brokenCode);
        return currCode;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM