String concatenation: concat() and "+" operators

Keywords: Java Programming

Suppose strings a and b:

a += b
a = a.concat(b)

Behind the scenes, are they the same thing?

Here you decompile concat as a reference. I also want to be able to decompile the + operator to see what it does.

public String concat(String s) {

    int i = s.length();
    if (i == 0) {
        return this;
    }
    else {
        char ac[] = new char[count + i];
        getChars(0, count, ac, 0);
        s.getChars(0, i, ac, count);
        return new String(0, count + i, ac);
    }
}

#1 building

Basically, there are two important differences between + and concat methods.

  1. If you use the concat method, you can only connect strings, and when you use the + operator, you can also connect strings to any data type.

    For example:

    String s = 10 + "Hello";

    In this case, the output should be 10Hello.

    String s = "I"; String s1 = s.concat("am").concat("good").concat("boy"); System.out.println(s1);

    In the above case, you must provide two required strings.

  2. +The second major difference between and concat is:

    Case 1: suppose I join the same string in this way with the concat operator

    String s="I"; String s1=s.concat("am").concat("good").concat("boy"); System.out.println(s1);

    In this case, the total number of objects created in the pool is 7, as follows:

    I am good boy Iam Iamgood Iamgoodboy

    Situation 2:

    Now, I'll hide the same string with the + operator

    String s="I"+"am"+"good"+"boy"; System.out.println(s);

    In this case, the total number of objects created is only 5.

    In fact, when we decorate a string with the + operator, it will maintain a StringBuffer class to perform the same task, as follows:

    StringBuffer sb = new StringBuffer("I"); sb.append("am"); sb.append("good"); sb.append("boy"); System.out.println(sb);

    This way, it will create only five objects.

So these are the basic differences between the + and concat methods. Please enjoy:)

#2 building

When + is used, the speed decreases with the increase of string length, but when concat is used, the speed is more stable. The best choice is to use StringBuilder class, which has stable speed.

I think you can understand why. However, the best way to create long strings is to use StringBuilder () and append (), both of which are unacceptable speeds.

#3 building

For the sake of completeness, I would like to add that In JLS SE8 15.18.1 Find the definition of the '+' operator:

If only one operand expression is of type String, String conversion is performed on the other operand (section 5.1.11) to generate the String at run time.

String concatenation results in a reference to a string object, which is a concatenation of two operand strings. In the newly created string, the character of the left operand precedes the character of the right operand.

Unless the expression is a constant expression (section 15.28), the String object is recreated (section 12.5).

With regard to implementation, JLS represents the following:

The implementation can choose to perform transformations and connections in one step to avoid creating and then discarding intermediate String objects. To improve the performance of repeated String connections, Java compilers can use StringBuffer classes or similar techniques to reduce the number of intermediate String objects created by evaluating expressions.

For basic types, the implementation can also optimize the creation of wrapper objects by directly converting from basic types to strings.

Therefore, judging from "Java compiler can use StringBuffer class or similar technology to reduce", different compilers may produce different bytecode.

#4 building

Most of the answers come from 2008. As time goes on, things seem to have changed. My latest benchmark is about twice as fast as the Java 8 + on programming by Jiangling Holding Co., Ltd.

My benchmark:

@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
public class StringConcatenation {

    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State2 {
        public String a = "abc";
        public String b = "xyz";
    }

    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State3 {
        public String a = "abc";
        public String b = "xyz";
        public String c = "123";
    }


    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State4 {
        public String a = "abc";
        public String b = "xyz";
        public String c = "123";
        public String d = "!@#";
    }

    @Benchmark
    public void plus_2(State2 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b);
    }

    @Benchmark
    public void plus_3(State3 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b+state.c);
    }

    @Benchmark
    public void plus_4(State4 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b+state.c+state.d);
    }

    @Benchmark
    public void stringbuilder_2(State2 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).toString());
    }

    @Benchmark
    public void stringbuilder_3(State3 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).toString());
    }

    @Benchmark
    public void stringbuilder_4(State4 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).append(state.d).toString());
    }

    @Benchmark
    public void concat_2(State2 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b));
    }

    @Benchmark
    public void concat_3(State3 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b.concat(state.c)));
    }


    @Benchmark
    public void concat_4(State4 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b.concat(state.c.concat(state.d))));
    }
}

Result:

Benchmark                             Mode  Cnt         Score         Error  Units
StringConcatenation.concat_2         thrpt   50  24908871.258 ± 1011269.986  ops/s
StringConcatenation.concat_3         thrpt   50  14228193.918 ±  466892.616  ops/s
StringConcatenation.concat_4         thrpt   50   9845069.776 ±  350532.591  ops/s
StringConcatenation.plus_2           thrpt   50  38999662.292 ± 8107397.316  ops/s
StringConcatenation.plus_3           thrpt   50  34985722.222 ± 5442660.250  ops/s
StringConcatenation.plus_4           thrpt   50  31910376.337 ± 2861001.162  ops/s
StringConcatenation.stringbuilder_2  thrpt   50  40472888.230 ± 9011210.632  ops/s
StringConcatenation.stringbuilder_3  thrpt   50  33902151.616 ± 5449026.680  ops/s
StringConcatenation.stringbuilder_4  thrpt   50  29220479.267 ± 3435315.681  ops/s

#5 building

+Operators work between strings and string, char, integer, double, or float data type values. It just converts the value to its string representation before connecting.

concat operators can only be done on strings and strings. It checks data type compatibility and throws an error if it doesn't match.

In addition, the code you provide has the same functionality.

Posted by rashu.dr on Sun, 19 Jan 2020 03:59:36 -0800