在Java中连接两个字符串的最快方法是什么?

Dan*_*Dan 36 java string performance

在Java中连接两个字符串的最快方法是什么?

String ccyPair = ccy1 + ccy2;
Run Code Online (Sandbox Code Playgroud)

cyPair在a中使用它作为键HashMap,它在一个非常紧凑的循环中被调用来检索值.

当我描述然后这是瓶颈

java.lang.StringBuilder.append(StringBuilder.java:119)  
java.lang.StringBuilder.(StringBuilder.java:93)
Run Code Online (Sandbox Code Playgroud)

Dun*_*gor 42

很多理论 - 一些练习的时间!

private final String s1 = new String("1234567890");
private final String s2 = new String("1234567890");
Run Code Online (Sandbox Code Playgroud)

在一台热身的64位热点上使用plain for 10,000,000循环,在Intel Mac OS上使用1.6.0_22.

例如

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

在循环中使用以下语句

String s3 = s1 + s2; 
Run Code Online (Sandbox Code Playgroud)

1.33s

String s3 = new StringBuilder(s1).append(s2).toString();
Run Code Online (Sandbox Code Playgroud)

1.28秒

String s3 = new StringBuffer(s1).append(s2).toString();
Run Code Online (Sandbox Code Playgroud)

1.92s

String s3 = s1.concat(s2);
Run Code Online (Sandbox Code Playgroud)

0.70s

String s3 = "1234567890" + "1234567890";
Run Code Online (Sandbox Code Playgroud)

0.0S

所以concat是明显的胜利者,除非你有静态字符串,在这种情况下编译器将会照顾你.

  • 代码将被优化,因此您可以有效地测试未优化的代码.这就是你不写微基准的方法.尽管如此,String.contact应该是2个字符串中最快的. (6认同)

Tho*_*sen 19

这些例程出现在基准测试中的原因是因为这就是编译器在封面下实现"+"的方式.

如果你真的需要连接字符串,你应该让编译器用"+"来实现它的魔力.如果你们都需要一个用于地图查找的键,那么一个包含适当equalshashMap实现的字符串的键类可能是一个好主意,因为它避免了复制步骤.

  • @Deepak,我不相信这是一个瓶颈,但在Eclipse 3.6中创建这样一个类的最简单方法是创建一个新类,给它字段ccy1和ccy2,让Eclipse创建一个基于的构造函数字段,并生成hashCode()和equals()方法. (2认同)

sfo*_*dal 19

我相信答案可能已经确定,但我发帖分享代码.

简短的回答,如果您正在寻找纯粹的连接,那就是:String.concat(...)

输出:

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
Run Code Online (Sandbox Code Playgroud)

示例代码:

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);
    }

}
Run Code Online (Sandbox Code Playgroud)


hab*_*713 7

您应该使用在运行时生成的String(如UUID.randomUUID().toString())进行测试,而不是在编译时(如"my string").我的结果是

plus:     118 ns
concat:    52 ns
builder1: 102 ns
builder2:  66 ns
buffer1:  119 ns
buffer2:   87 ns
Run Code Online (Sandbox Code Playgroud)

有了这个实现:

private static long COUNT = 10000000;

public static void main(String[] args) throws Exception {
    String s1 = UUID.randomUUID().toString();
    String s2 = UUID.randomUUID().toString();
    for(String methodName : new String[] {
            "none", "plus", "concat", "builder1", "builder2", "buffer1", "buffer2"
    }) {
        Method method = ConcatPerformanceTest.class.getMethod(methodName, String.class, String.class);
        long time = System.nanoTime();
        for(int i = 0; i < COUNT; i++) {
            method.invoke((Object) null, s1, s2);
        }
        System.out.println(methodName + ": " + (System.nanoTime() - time)/COUNT + " ns");
    }
}

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

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

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

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

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

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

public static String buffer2(String s1, String s2) {
    return new StringBuffer(s1.length() + s2.length()).append(s1).append(s2).toString();
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*ine 5

对于标题中的问题:String.concat通常是连接两个Strings 的最快方式(但请注意null).不涉及[超大]中间缓冲区或其他对象.奇怪的+是编译成相对低效的代码涉及StringBuilder.

但是,你的身体问题指向其他问题.用于为地图生成键的字符串连接是常见的"反成语".这是一个黑客,容易出错.您确定生成的密钥是唯一的吗?在为某些尚未知的要求维护代码后,它是否仍然是唯一的?最好的方法是为密钥创建一个不可变的值类.使用List和通用元组类是一个草率的黑客.