performance – Whats the fastest way to concatenate two Strings in Java?

performance – Whats the fastest way to concatenate two Strings in Java?

Lots of theory – time for some practice!

private final String s1 = new String(1234567890);
private final String s2 = new String(1234567890);

Using plain for loops of 10,000,000, on a warmed-up 64-bit Hotspot, 1.6.0_22 on Intel Mac OS.

eg

@Test public void testConcatenation() {
    for (int i = 0; i < COUNT; i++) {
        String s3 = s1 + s2;
    }
}

With the following statements in the loops

String s3 = s1 + s2; 

1.33s

String s3 = new StringBuilder(s1).append(s2).toString();

1.28s

String s3 = new StringBuffer(s1).append(s2).toString();

1.92s

String s3 = s1.concat(s2);

0.70s

String s3 = 1234567890 + 1234567890;

0.0s

So concat is the clear winner, unless you have static strings, in which case the compiler will have taken care of you already.

I believe the answer might have already been determined, but I post to share the code.

Short answer, if pure concatenation is all you are looking for, is: String.concat(…)

Output:

ITERATION_LIMIT1: 1
ITERATION_LIMIT2: 10000000
s1: STRING1-1111111111111111111111
s2: STRING2-2222222222222222222222

iteration: 1
                                          null:    1.7 nanos
                                 s1.concat(s2):  106.1 nanos
                                       s1 + s2:  251.7 nanos
   new StringBuilder(s1).append(s2).toString():  246.6 nanos
    new StringBuffer(s1).append(s2).toString():  404.7 nanos
                 String.format(%s%s, s1, s2): 3276.0 nanos

Tests complete

Sample Code:

package net.fosdal.scratch;

public class StringConcatenationPerformance {
    private static final int    ITERATION_LIMIT1    = 1;
    private static final int    ITERATION_LIMIT2    = 10000000;

    public static void main(String[] args) {
        String s1 = STRING1-1111111111111111111111;
        String s2 = STRING2-2222222222222222222222;
        String methodName;
        long startNanos, durationNanos;
        int iteration2;

        System.out.println(ITERATION_LIMIT1:  + ITERATION_LIMIT1);
        System.out.println(ITERATION_LIMIT2:  + ITERATION_LIMIT2);
        System.out.println(s1:  + s1);
        System.out.println(s2:  + s2);
        int iteration1 = 0;
        while (iteration1++ < ITERATION_LIMIT1) {
            System.out.println();
            System.out.println(iteration:  + iteration1);

            // method #0
            methodName = null;
            iteration2 = 0;
            startNanos = System.nanoTime();
            while (iteration2++ < ITERATION_LIMIT2) {
                method0(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format(%50s: %6.1f nanos, methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #1
            methodName = s1.concat(s2);
            iteration2 = 0;
            startNanos = System.nanoTime();
            while (iteration2++ < ITERATION_LIMIT2) {
                method1(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format(%50s: %6.1f nanos, methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #2
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = s1 + s2;
            while (iteration2++ < ITERATION_LIMIT2) {
                method2(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format(%50s: %6.1f nanos, methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #3
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = new StringBuilder(s1).append(s2).toString();
            while (iteration2++ < ITERATION_LIMIT2) {
                method3(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format(%50s: %6.1f nanos, methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #4
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = new StringBuffer(s1).append(s2).toString();
            while (iteration2++ < ITERATION_LIMIT2) {
                method4(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format(%50s: %6.1f nanos, methodName, ((double) durationNanos) / ITERATION_LIMIT2));

            // method #5
            iteration2 = 0;
            startNanos = System.nanoTime();
            methodName = String.format(%s%s, s1, s2);
            while (iteration2++ < ITERATION_LIMIT2) {
                method5(s1, s2);
            }
            durationNanos = System.nanoTime() - startNanos;
            System.out.println(String.format(%50s: %6.1f nanos, methodName, ((double) durationNanos) / ITERATION_LIMIT2));

        }
        System.out.println();
        System.out.println(Tests complete);

    }

    public static String method0(String s1, String s2) {
        return ;
    }

    public static String method1(String s1, String s2) {
        return s1.concat(s2);
    }

    public static String method2(String s1, String s2) {
        return s1 + s2;
    }

    public static String method3(String s1, String s2) {
        return new StringBuilder(s1).append(s2).toString();
    }

    public static String method4(String s1, String s2) {
        return new StringBuffer(s1).append(s2).toString();
    }

    public static String method5(String s1, String s2) {
        return String.format(%s%s, s1, s2);
    }

}

performance – Whats the fastest way to concatenate two Strings in Java?

The reason why these routines show up in the benchmark is because that is how the compiler implements your + under the covers.

If you really need the concatenated string, you should let the compiler do its magic with the +. If all you need is a key for map lookup, a key class holding both strings with suitable equals and hashMap implementations might be a good idea as it avoids the copying step.

Leave a Reply

Your email address will not be published. Required fields are marked *