2
\$\begingroup\$

Can random string generation be faster in Java?

Here is my current code

import java.util.ArrayList;
import java.util.List;

public class FastestStringGeneration {

    private static final String ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static final char[] ch = ALPHA_NUMERIC_STRING.toCharArray();
    private static final java.util.concurrent.ThreadLocalRandom random = java.util.concurrent.ThreadLocalRandom.current();

    public static void main(String[] java) {
        // warmup code
        String[] warmUp = new String[10000];
        for (int j=0; j<10000; j++){
           warmUp[j] = getAlphaNumeric(1024);
        }
        // real code begins
        int numIterations = 1000000;
        String[] randomStrings = new String[numIterations];
        long start = System.currentTimeMillis();
        for(int i=0; i<numIterations; i++){
            randomStrings[i] = getAlphaNumeric(1024);
        }
        System.out.println(System.currentTimeMillis()-start);
        System.out.println(randomStrings.length);
    }

    public static String getAlphaNumeric(int len) {
        char[] c = new char[len];
        for (int i = 0; i < len; i++) {
            c[i] = ch[random.nextInt(ch.length)];
        }
        return new String(c);
    }
}

The total time it takes to generate 1 million random strings is about ~ 5.9 seconds. Can it be faster?

I was using java.util.Random but when I changed to java.util.concurrent.ThreadLocalRandom according to comments below I got the most performance improvement!

\$\endgroup\$
  • \$\begingroup\$ I was trying in other languages and was able to accomplish in ~5 seconds. \$\endgroup\$ – user1870400 Oct 23 '18 at 8:45
  • \$\begingroup\$ I have this code in one of my application and that is where it spends the most time and yeah the faster implementation I found on other languages doesn't seem to use Random everytime instead some crazy bit shifting logic so I am wondering if anyone here could possibly come up with a solution \$\endgroup\$ – user1870400 Oct 23 '18 at 8:45
  • \$\begingroup\$ For sure you have a big overhead due to the initial size of your array that's is 10 (as default). I suggest to initialize it with new ArrayList<>(numIterations). More, you can avoid List<> and use String[]. This will cut overhead about list managment before alghorytm that can use bitwise operations to be faster. \$\endgroup\$ – MrPk Oct 23 '18 at 8:48
  • 2
    \$\begingroup\$ use private static java.util.concurrent.ThreadLocalRandom random = ThreadLocalRandom.current(); instead of java.util.Random. The java.util.Random uses locks to be thread-safe, it slows down execution. \$\endgroup\$ – user158037 Oct 23 '18 at 15:00
  • 1
    \$\begingroup\$ Welp. No. I thought that was you. Ehm. They should write an answer as well then 😅 \$\endgroup\$ – Vogel612 Oct 23 '18 at 18:18
1
\$\begingroup\$

If the length is always identical you can save 1000000 calls to new().

Because new String(char[]) uses Arrays.copyOf(), you don't need a new char[] in every loop.

private static int ourlen = 1024;
private static char[] chars = new char[ourlen];

public static String getAlphaNumeric() {
    for (int i = 0; i < ourlen; i++) {
        chars[i] = ch[random.nextInt(ch.length)];
    }
    return new String(c);
}
\$\endgroup\$
  • \$\begingroup\$ True. 300ms gain! Tells me Java object creation is awesome! \$\endgroup\$ – user1870400 Oct 24 '18 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.