2

Is there a way to generate a unique surrogate string like UUID.randomUUID() but containing characters only (means no numbers)? The string is stored in multiple databases on different hosts and has to be system wide unique (even if I generate two keys at the same time - i.e. by threads).

KIC
  • 5,887
  • 7
  • 58
  • 98
  • What do you mean characters only? If you do a .toString() on the UUID then you'll get a hex representation. – Dan Aug 31 '12 at 12:37
  • @Dan Matthews-Grout sorry edited my question - char only means no numbers/digits -> just letters a-Z – KIC Aug 31 '12 at 12:38
  • Why can't you have numbers in the string? – Michael Lloyd Lee mlk Aug 31 '12 at 12:40
  • Exact duplicate of http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string-in-java – Germann Arlington Aug 31 '12 at 12:41
  • @mlk because the keys are later getting parsed and the parser only accept letters. it is a mathematical parser, strings of letters refer to variables (the values I store with the unique keys). if there are numbers - i.e. a13 the parser "thinks" you mean a * 13. the parser is not part of my project :-( – KIC Aug 31 '12 at 12:45
  • 2
    If you want to make sure that random string **are** unique you will have to store the ones that you already used and retry getting next random string if you found a duplicate. – Germann Arlington Aug 31 '12 at 12:49

5 Answers5

2

Apache Commons Lang 3 has a class named RandomStringUtils that can be used to obtain random alphabetic strings:

int stringSize = 8;  // just choose the size better suits you
String randomString = RandomStringUtils.randomAlphabetic(stringSize);

If you need this to be unique even when more than one thread is running then you will need a way to synchronize them (maybe using synchronized blocks and a while loop) and checking in that database that no previous string equal to the generated one exists.

EDIT - A rough example

Set<String> previousKeys = new HashSet<String>();

public String generateKey(int stringSize) {
    String randomString = "";
    synchronized(previousKeys) {
        do {
            randomString = RandomStringUtils.randomAlphabetic(stringSize);
        } while (randomString.length() == 0 || !previousKeys.add(randomString));
    }
    return randomString;
}
Alonso Dominguez
  • 7,750
  • 1
  • 27
  • 37
1

Just wrote this - random string of upper case characters:

package dan;

import java.util.Random;

public class RandText {

    /**
     * @param args
     */
    public static void main(String[] args) {

        String s = getRandomText(100);
        System.out.println(s);

    }


    public static String getRandomText(int len) {
        StringBuilder b = new StringBuilder();
        Random r = new Random();
        for (int i = 0; i<len;i++) {
            char c = (char)(65+r.nextInt(25));
            b.append(c);
        }
        return b.toString();
    }
}
Dan
  • 1,030
  • 5
  • 12
  • 1
    but he was using the UUID before which is just random but large. It's just the size of the string that makes the probability of generating the same ID twice incredibly small. The probabilty of a clash is n^x where x is the length and n is the character space - in this case 26^x - at 100 chars long that is incrediblely rare and could be called unique. – Dan Aug 31 '12 at 12:48
  • If uniqueness is not a strict requirement, your approach works (although you might want to use a better random generator). If it is a strict requirement, you need to check each key to make sure it is unique. – assylias Aug 31 '12 at 12:51
  • but he was willing to use UUID as long as it didn't generate numbers. I just don't get the point of your argument. Implementing such a system would put a large overhead on insertions. That's the point of the UUID generator - that the space is large enough that you don't get clashes. I also don't get the point about the random number generator - what do you want - him to go out and buy a hardware unit? – Dan Aug 31 '12 at 12:54
  • 1
    I understand your point - I'm just saying that getting 2 identical keys from UUID is (very) low probability but not impossible. The OP needs to decide if he is happy with that low probability event or not (he might not know that UUID does not guarantee uniqueness). Regarding the random generator, [SecureRandom is preferable](http://stackoverflow.com/questions/11051205/difference-between-java-util-random-and-java-security-securerandom). – assylias Aug 31 '12 at 13:00
  • 1
    Since uniquenes is not garantied anyway, I prefer this solution over the apache commons lang (since I had to use an additional lib). I will generate surrogates (synchonized) the size of 100 chars. If there will be the first duplicate I will do a "bugfix" :-) maybe I have to find a solution where all keys are redundant stored on a specific machine then. ... but I want to get around of this ... – KIC Aug 31 '12 at 13:06
  • The chance of a duplicate (if the randomness is perfect) is 1 in 26^100 - which it is more likely that the universe will spontaeniously end before that happens. But the randomness won't be perfect. One improvement, would be as suggested by assylias, is to use SecureRandom. Out of interest I'm running an experiment with a 32 character string and trying to find a duplicate. So far I have run out of heap and have had to go above a gigabyte, still running. – Dan Aug 31 '12 at 13:10
  • Given up testing - I run out of heap at 8,976,769th generated value but no duplicates produced. I only have a limited amount of physical ram due to working on a VM. – Dan Aug 31 '12 at 13:18
  • @Dan Matthews-Grout so hopefully the universe is not stopping the next few years suddenly :-) Thanks for doing the extra test! – KIC Aug 31 '12 at 13:26
0

if you are looking to generate random characters, use a random int generator, and have it generate a random number 65 - 122. keep in mind that 91-96 are not A-Z or a-z in ascii, though. Keep in mind you will want to convert this int to a char.

This can be helpful: http://www.asciitable.com/

tehdoommarine
  • 1,868
  • 3
  • 18
  • 31
0
String id = UUID.randomUUID().toString().replaceAll("-", "");
id.replaceAll("0","zero");
// [...]
id.replaceAll("9","nine");

I am feeling bad about this approach.

Christian Kuetbach
  • 15,850
  • 5
  • 43
  • 79
0

Grab your UUID, strip out the "-"s. Convert char '1' -> 'Z', '2' -> 'Y' etc.

Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81