StringBuilder vs String concatenation in toString() in Java

后端 未结 18 2192
北恋
北恋 2020-11-21 04:18

Given the 2 toString() implementations below, which one is preferred:

public String toString(){
    return \"{a:\"+ a + \", b:\" + b + \", c: \"         


        
18条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-21 05:06

    See the example below:

    static final int MAX_ITERATIONS = 50000;
    static final int CALC_AVG_EVERY = 10000;
    
    public static void main(String[] args) {
        printBytecodeVersion();
        printJavaVersion();
        case1();//str.concat
        case2();//+=
        case3();//StringBuilder
    }
    
    static void case1() {
        System.out.println("[str1.concat(str2)]");
        List savedTimes = new ArrayList();
        long startTimeAll = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < MAX_ITERATIONS; i++) {
            long startTime = System.currentTimeMillis();
            str = str.concat(UUID.randomUUID() + "---");
            saveTime(savedTimes, startTime);
        }
        System.out.println("Created string of length:" + str.length() + " in " + (System.currentTimeMillis() - startTimeAll) + " ms");
    }
    
    static void case2() {
        System.out.println("[str1+=str2]");
        List savedTimes = new ArrayList();
        long startTimeAll = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < MAX_ITERATIONS; i++) {
            long startTime = System.currentTimeMillis();
            str += UUID.randomUUID() + "---";
            saveTime(savedTimes, startTime);
        }
        System.out.println("Created string of length:" + str.length() + " in " + (System.currentTimeMillis() - startTimeAll) + " ms");
    }
    
    static void case3() {
        System.out.println("[str1.append(str2)]");
        List savedTimes = new ArrayList();
        long startTimeAll = System.currentTimeMillis();
        StringBuilder str = new StringBuilder("");
        for (int i = 0; i < MAX_ITERATIONS; i++) {
            long startTime = System.currentTimeMillis();
            str.append(UUID.randomUUID() + "---");
            saveTime(savedTimes, startTime);
        }
        System.out.println("Created string of length:" + str.length() + " in " + (System.currentTimeMillis() - startTimeAll) + " ms");
    
    }
    
    static void saveTime(List executionTimes, long startTime) {
        executionTimes.add(System.currentTimeMillis() - startTime);
        if (executionTimes.size() % CALC_AVG_EVERY == 0) {
            out.println("average time for " + executionTimes.size() + " concatenations: "
                    + NumberFormat.getInstance().format(executionTimes.stream().mapToLong(Long::longValue).average().orElseGet(() -> 0))
                    + " ms avg");
            executionTimes.clear();
        }
    }
    

    Output:

    java bytecode version:8
    java.version: 1.8.0_144
    [str1.concat(str2)]
    average time for 10000 concatenations: 0.096 ms avg
    average time for 10000 concatenations: 0.185 ms avg
    average time for 10000 concatenations: 0.327 ms avg
    average time for 10000 concatenations: 0.501 ms avg
    average time for 10000 concatenations: 0.656 ms avg
    Created string of length:1950000 in 17745 ms
    [str1+=str2]
    average time for 10000 concatenations: 0.21 ms avg
    average time for 10000 concatenations: 0.652 ms avg
    average time for 10000 concatenations: 1.129 ms avg
    average time for 10000 concatenations: 1.727 ms avg
    average time for 10000 concatenations: 2.302 ms avg
    Created string of length:1950000 in 60279 ms
    [str1.append(str2)]
    average time for 10000 concatenations: 0.002 ms avg
    average time for 10000 concatenations: 0.002 ms avg
    average time for 10000 concatenations: 0.002 ms avg
    average time for 10000 concatenations: 0.002 ms avg
    average time for 10000 concatenations: 0.002 ms avg
    Created string of length:1950000 in 100 ms

    As the string length increases, so does the concatenation time.
    That is where the StringBuilder is definitely needed.
    As you see, the concatenation: UUID.randomUUID()+"---", does not really affect the time.

    P.S.: I don't think When to use StringBuilder in Java is really a duplicate of this.
    This question talks about toString() which most of the times does not perform concatenations of huge strings.


    2019 Update

    Since java8 times, things have changed a bit. It seems that now(java13), the concatenation time of += is practically the same as str.concat(). However StringBuilder concatenation time is still constant. (Original post above was slightly edited to add more verbose output)

    java bytecode version:13
    java.version: 13.0.1
    [str1.concat(str2)]
    average time for 10000 concatenations: 0.047 ms avg
    average time for 10000 concatenations: 0.1 ms avg
    average time for 10000 concatenations: 0.17 ms avg
    average time for 10000 concatenations: 0.255 ms avg
    average time for 10000 concatenations: 0.336 ms avg
    Created string of length:1950000 in 9147 ms
    [str1+=str2]
    average time for 10000 concatenations: 0.037 ms avg
    average time for 10000 concatenations: 0.097 ms avg
    average time for 10000 concatenations: 0.249 ms avg
    average time for 10000 concatenations: 0.298 ms avg
    average time for 10000 concatenations: 0.326 ms avg
    Created string of length:1950000 in 10191 ms
    [str1.append(str2)]
    average time for 10000 concatenations: 0.001 ms avg
    average time for 10000 concatenations: 0.001 ms avg
    average time for 10000 concatenations: 0.001 ms avg
    average time for 10000 concatenations: 0.001 ms avg
    average time for 10000 concatenations: 0.001 ms avg
    Created string of length:1950000 in 43 ms

    Worth noting also bytecode:8/java.version:13 combination has a good performance benefit compared to bytecode:8/java.version:8

提交回复
热议问题