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\$
22
  • \$\begingroup\$ I was trying in other languages and was able to accomplish in ~5 seconds. \$\endgroup\$ Commented Oct 23, 2018 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\$ Commented Oct 23, 2018 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
    Commented Oct 23, 2018 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
    Commented Oct 23, 2018 at 15:00
  • 1
    \$\begingroup\$ Welp. No. I thought that was you. Ehm. They should write an answer as well then 😅 \$\endgroup\$
    – Vogel612
    Commented Oct 23, 2018 at 18:18

1 Answer 1

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\$
1
  • \$\begingroup\$ True. 300ms gain! Tells me Java object creation is awesome! \$\endgroup\$ Commented Oct 24, 2018 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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