12

Is there any way to generate 8 characters long random and unique String in Java?

String id = getRandomString();

and then id will be for example wf41Av5g

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
danny.lesnik
  • 18,479
  • 29
  • 135
  • 200
  • 1
    Not if you want more than 62^8 of them (assuming you want alphanumerics only)... you probably want a random string, then lookup against a table of already generated strings. –  Oct 17 '11 at 09:01
  • 6
    define "unique": every time the method is ran a different string is returned? or all chars are different from each other? something else? – amit Oct 17 '11 at 09:03

12 Answers12

27

You can use RandomStringUtils

import org.apache.commons.lang.RandomStringUtils;
public class RandomStringUtilsTrial {
  public static void main(String[] args) {
    System.out.print("8 char string  >>>");
    System.out.println(RandomStringUtils.random(8, true, true));

  }
}
muttonUp
  • 6,351
  • 2
  • 42
  • 54
bilash.saha
  • 7,226
  • 2
  • 35
  • 40
  • 23
    I am curious, how does this solve the OP's question. I don't see anything in the documentation that ensures uniqueness. – taylorcressy May 14 '15 at 03:05
15

The uniqueness property depends on the scope in which you use it. Java can certainly generate random strings, although if you want a universally unique identifier you can use UUID class.

String unique = UUID.randomUUID().toString();
Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
  • 3
    It's good but I need 8 characters only, otherwise I would use it without and doubt. – danny.lesnik Oct 17 '11 at 09:22
  • 2
    UUIDs are structured; their fields are generated in particular ways, and not every bit is equally unique. That means you can't just slice random bits off them and expect them to stay unique. See Danny's comment on [Oliver's answer](http://stackoverflow.com/questions/7791475/8-chars-unique-string-in-java/7791522#7791522) for an illustration of this problem in action. – Tom Anderson Oct 17 '11 at 09:31
  • 2
    @danny, [i.e.,](http://ideone.com/GKniz) `String eightChars = unique.substring(28);` – Johan Sjöberg Oct 17 '11 at 09:32
14

If the uniqueness is important, you can't simply randomly generate strings. There is no way to avoid a collision. Even UUIDs can collide, although it is quite unlikely.

You could keep a record of the strings you've used, and when you generate a new random string, check the record to see if it's a duplicate, and if so, discard it and try again.

However, what i would suggest is that you don't generate random numbers. Instead, keep a counter, and encrypt its output to produce random-looking numbers. These are guaranteed never to collide if you do this properly. See an earlier answer of mine, or one by Rossum

Community
  • 1
  • 1
Tom Anderson
  • 46,189
  • 17
  • 92
  • 133
6

You can create this string on base of the current time.

For example:

2014 06 04 16 21 20 79 ---> 14 06 04 16 21 20 79

Then you can translate every two digits (except last two) for an alphanumeric character using table ( http://en.wikipedia.org/wiki/Base64 - note that all of them are smaller than 59)

then you will receive

14 - O
06 - G
04 - E
16 - Q
21 - V
20 - U

OGEQVU79 <- exactly 8 characters. A little bit complicated, but it works if you would not call your function often than 0.01 s

surcho
  • 61
  • 1
  • 1
  • This doesn't guarantee uniqueness - think about concurrent threads or even a single thread doing this repeatedly in very quick succession – wi2ard Jan 28 '21 at 15:03
1

As none of the answers above ensures uniqueness, I decided to add another answer.

First we define all valid options in an array:

char[] chars = new char[]{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

Now we can mutate the algorithm to Random shuffling of an array, to get the first 8 elements:

Random rnd = new Random();
int charsLength = chars.length;
int passLength = 8;
StringBuilder password = new StringBuilder();
for (int i = 0; i < passLength; i++)
{
    int index = rnd.nextInt(charsLength - i - 1);
    // Simple swap
    char a = chars[i + index];
    chars[i + index] = chars[i];
    chars[i] = a;
    password.append(a);
}

System.out.print(password);

It ensures uniqueness by that once a char is in the 8 first places of the array, it is not a valid choice for the next round.

Few outputs that I got:

ifJjuYrR
NpY3TfIU
LGFm8Ng9
sV4Gctb7
4fyhlSuQ
Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
1
public String getRandomString(int length, char[] characterSet) {
    StringBuilder sb = new StringBuilder();

    for (int loop = 0; loop < length; loop++) {
        int index = new Random().nextInt(characterSet.length);
        sb.append(characterSet[index]);
    }

    String nonce = sb.toString();
    return nonce;
}
epoch
  • 16,396
  • 4
  • 43
  • 71
0

By now you must've gotten your answer, but for those who reach this page, try this code:

public class RandomValueXML {

    public static void main(String[] args) {
        
        System.out.println(org.apache.commons.lang3.RandomStringUtils.random(6, true, true)); 

    }
    
    static Set<String> getRandomUniqueStrings(int count, int length, boolean letters, boolean numbers){
        Set<String> rus = new HashSet<>();
        
        while (rus.size() < count){
            rus.add(RandomStringUtils.random(length, letters, numbers));
        }
        
        return rus;
    } 
}

Here the use of set ensures the uniqueness while use of HashSet ensures better performance while reading and writing.

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
Anup
  • 1
  • Please note that the accepted answer is what you suggest. Are you adding on top of it? Please take the [tour] and read [answer]. – Tomer Shetah Jan 07 '21 at 09:51
0

I know this is an old post but this may help someone.

This one worked for me:

System.out.println(UniqueIdGenerator.fromBase10(System.currentTimeMillis()));

should be unique in every millisecond on the same JVM.

with:

public class UniqueIdGenerator {

 private static final String MIX_STRING = "abcdefghijklmnopqrstuvwxyz1234567890";

 private static final int MIX_STRING_LENGTH = MIX_STRING.length();

 public static String fromBase10(final long base10) {
    if (base10 == 0)
        return "0";

    long temp = base10;
    final StringBuilder sb = new StringBuilder();

    while (temp > 0) {
        temp = fromBase10(temp, sb);
    }
    return sb.reverse().toString();
 }

 private static Long fromBase10(final long base10, final StringBuilder sb) {
    final int rem = (int) (base10 % MIX_STRING_LENGTH);
    sb.append(MIX_STRING.charAt(rem));
    return base10 / MIX_STRING_LENGTH;
 }
}

you can also change the char order in MIX_STRING, even add upperCase letters or symbols.

Jay Ehsaniara
  • 1,421
  • 17
  • 24
0

I have got no idea whether there is a method that can produce 8 digit unique random string but I would create an offline key-generator-service that constantly generates random keys and insert them to key table if the key does not exist in the table and whenever your online app needs a key then it can fetch from one of the pre-produced keys.

Aksoy
  • 91
  • 1
  • 8
  • Hello and welcome to SO! Please read the [tour](https://stackoverflow.com/tour), and [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) I don't think that this is what the PO asked for. – Tomer Shetah Jan 07 '21 at 09:38
0

Quick and dirty solution using java.util.UUID:

public String getRandomString(int length) {
    return UUID.randomUUID().toString().subSequence(0, length);
}
helpermethod
  • 59,493
  • 71
  • 188
  • 276
  • 8
    I generated it twice and ff808181328864ba01328864bc590000 and ff808181328864ba02328864bc5902300. If I take only 8 first chars I will get the same string :( – danny.lesnik Oct 17 '11 at 09:26
0

Please try following code:

private String uniqid() {
    Random random = new Random();
    String tag = Long.toString(Math.abs(random.nextLong()), 36);
    return tag.substring(0, 8);
}
Tran Dinh Thoai
  • 712
  • 1
  • 7
  • 21
  • I believe that this doesn't *quite* do the right thing, because Long.toString drops leading zeroes. However, you could extend the code to zero-pad short strings instead of trimming them. – Tom Anderson Oct 17 '11 at 09:20
-2
long unixTime = System.currentTimeMillis() / 1000L;
String unique_no=Long.toHexString(unixTime).toUpperCase();

gives you unique 8 chars String in HEX format.

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114