(Java) What is the point of using `concat()`? [duplicate] - java

Assuming String a and b:
a += b
a = a.concat(b)
Under the hood, are they the same thing?
Here is concat decompiled as reference. I'd like to be able to decompile the + operator as well to see what that 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);
}
}

No, not quite.
Firstly, there's a slight difference in semantics. If a is null, then a.concat(b) throws a NullPointerException but a+=b will treat the original value of a as if it were null. Furthermore, the concat() method only accepts String values while the + operator will silently convert the argument to a String (using the toString() method for objects). So the concat() method is more strict in what it accepts.
To look under the hood, write a simple class with a += b;
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
Now disassemble with javap -c (included in the Sun JDK). You should see a listing including:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
So, a += b is the equivalent of
a = new StringBuilder()
.append(a)
.append(b)
.toString();
The concat method should be faster. However, with more strings the StringBuilder method wins, at least in terms of performance.
The source code of String and StringBuilder (and its package-private base class) is available in src.zip of the Sun JDK. You can see that you are building up a char array (resizing as necessary) and then throwing it away when you create the final String. In practice memory allocation is surprisingly fast.
Update: As Pawel Adamski notes, performance has changed in more recent HotSpot. javac still produces exactly the same code, but the bytecode compiler cheats. Simple testing entirely fails because the entire body of code is thrown away. Summing System.identityHashCode (not String.hashCode) shows the StringBuffer code has a slight advantage. Subject to change when the next update is released, or if you use a different JVM. From #lukaseder, a list of HotSpot JVM intrinsics.

Niyaz is correct, but it's also worth noting that the special + operator can be converted into something more efficient by the Java compiler. Java has a StringBuilder class which represents a non-thread-safe, mutable String. When performing a bunch of String concatenations, the Java compiler silently converts
String a = b + c + d;
into
String a = new StringBuilder(b).append(c).append(d).toString();
which for large strings is significantly more efficient. As far as I know, this does not happen when you use the concat method.
However, the concat method is more efficient when concatenating an empty String onto an existing String. In this case, the JVM does not need to create a new String object and can simply return the existing one. See the concat documentation to confirm this.
So if you're super-concerned about efficiency then you should use the concat method when concatenating possibly-empty Strings, and use + otherwise. However, the performance difference should be negligible and you probably shouldn't ever worry about this.

I ran a similar test as #marcio but with the following loop instead:
String c = a;
for (long i = 0; i < 100000L; i++) {
c = c.concat(b); // make sure javac cannot skip the loop
// using c += b for the alternative
}
Just for good measure, I threw in StringBuilder.append() as well. Each test was run 10 times, with 100k reps for each run. Here are the results:
StringBuilder wins hands down. The clock time result was 0 for most the runs, and the longest took 16ms.
a += b takes about 40000ms (40s) for each run.
concat only requires 10000ms (10s) per run.
I haven't decompiled the class to see the internals or run it through profiler yet, but I suspect a += b spends much of the time creating new objects of StringBuilder and then converting them back to String.

Most answers here are from 2008. It looks that things have changed over the time. My latest benchmarks made with JMH shows that on Java 8 + is around two times faster than concat.
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))));
}
}
Results:
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

Tom is correct in describing exactly what the + operator does. It creates a temporary StringBuilder, appends the parts, and finishes with toString().
However, all of the answers so far are ignoring the effects of HotSpot runtime optimizations. Specifically, these temporary operations are recognized as a common pattern and are replaced with more efficient machine code at run-time.
#marcio: You've created a micro-benchmark; with modern JVM's this is not a valid way to profile code.
The reason run-time optimization matters is that many of these differences in code -- even including object-creation -- are completely different once HotSpot gets going. The only way to know for sure is profiling your code in situ.
Finally, all of these methods are in fact incredibly fast. This might be a case of premature optimization. If you have code that concatenates strings a lot, the way to get maximum speed probably has nothing to do with which operators you choose and instead the algorithm you're using!

How about some simple testing? Used the code below:
long start = System.currentTimeMillis();
String a = "a";
String b = "b";
for (int i = 0; i < 10000000; i++) { //ten million times
String c = a.concat(b);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
The "a + b" version executed in 2500ms.
The a.concat(b) executed in 1200ms.
Tested several times. The concat() version execution took half of the time on average.
This result surprised me because the concat() method always creates a new string (it returns a "new String(result)". It's well known that:
String a = new String("a") // more than 20 times slower than String a = "a"
Why wasn't the compiler capable of optimize the string creation in "a + b" code, knowing the it always resulted in the same string? It could avoid a new string creation.
If you don't believe the statement above, test for your self.

Basically, there are two important differences between + and the concat method.
If you are using the concat method then you would only be able to concatenate strings while in case of the + operator, you can also concatenate the string with 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 have to provide two strings mandatory.
The second and main difference between + and concat is that:
Case 1:
Suppose I concat the same strings with concat operator in this way
String s="I";
String s1=s.concat("am").concat("good").concat("boy");
System.out.println(s1);
In this case total number of objects created in the pool are 7 like this:
I
am
good
boy
Iam
Iamgood
Iamgoodboy
Case 2:
Now I am going to concatinate the same strings via + operator
String s="I"+"am"+"good"+"boy";
System.out.println(s);
In the above case total number of objects created are only 5.
Actually when we concatinate the strings via + operator then it maintains 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);
In this way it will create only five objects.
So guys these are the basic differences between + and the concat method.
Enjoy :)

For the sake of completeness, I wanted to add that the definition of the '+' operator can be found in the JLS SE8 15.18.1:
If only one operand expression is of type String, then string
conversion (§5.1.11) is performed on the other operand to produce a
string at run time.
The result of string concatenation is a reference to a String object
that is the concatenation of the two operand strings. The characters
of the left-hand operand precede the characters of the right-hand
operand in the newly created string.
The String object is newly created (§12.5) unless the expression is a
constant expression (§15.28)
About the implementation the JLS says the following:
An implementation may choose to perform conversion and concatenation
in one step to avoid creating and then discarding an intermediate
String object. To increase the performance of repeated string
concatenation, a Java compiler may use the StringBuffer class or a
similar technique to reduce the number of intermediate String objects
that are created by evaluation of an expression.
For primitive types, an implementation may also optimize away the
creation of a wrapper object by converting directly from a primitive
type to a string.
So judging from the 'a Java compiler may use the StringBuffer class or a similar technique to reduce', different compilers could produce different byte-code.

The + operator can work between a string and a string, char, integer, double or float data type value. It just converts the value to its string representation before concatenation.
The concat operator can only be done on and with strings. It checks for data type compatibility and throws an error, if they don't match.
Except this, the code you provided does the same stuff.

I don't think so.
a.concat(b) is implemented in String and I think the implementation didn't change much since early java machines. The + operation implementation depends on Java version and compiler. Currently + is implemented using StringBuffer to make the operation as fast as possible. Maybe in the future, this will change. In earlier versions of java + operation on Strings was much slower as it produced intermediate results.
I guess that += is implemented using + and similarly optimized.

When using +, the speed decreases as the string's length increases, but when using concat, the speed is more stable, and the best option is using the StringBuilder class which has stable speed in order to do that.
I guess you can understand why. But the totally best way for creating long strings is using StringBuilder() and append(), either speed will be unacceptable.

Note that s.concat("hello"); would result in a NullPointereException when s is null. In Java, the behavior of the + operator is usually determined by the left operand:
System.out.println(3 + 'a'); //100
However, Strings are an exception. If either operand is a String, the result is expected to be a String. This is the reason null is converted into "null", even though you might expect a RuntimeException.

Related

How many String objects would be created when concatenating multiple Strings?

I was asked in an interview about the number of objects that will be created on the given problem:
String str1 = "First";
String str2 = "Second";
String str3 = "Third";
String str4 = str1 + str2 + str3;
I answered that there would be 6 objects created in the string pool.
3 would be for each of the three variables.
1 would be for str1 + str2 (let's say str).
1 would be for str2 + str3.
1 would be for the str + str3 (str = str1 + str2).
Is the answer I gave correct? If not, what is the correct answer?
Any answer to your question will depend on the JVM implementation and the Java version currently being used. I think it's an unreasonable question to ask in an interview.
Java 8
On my machine, with Java 1.8.0_201, your snippet results in this bytecode
L0
LINENUMBER 13 L0
LDC "First"
ASTORE 1
L1
LINENUMBER 14 L1
LDC "Second"
ASTORE 2
L2
LINENUMBER 15 L2
LDC "Third"
ASTORE 3
L3
LINENUMBER 16 L3
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 3
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 4
which proves that 5 objects are being created (3 String literals*, 1 StringBuilder, 1 dynamically produced String instance by StringBuilder#toString).
Java 12
On my machine, with Java 12.0.2, the bytecode is
// identical to the bytecode above
L3
LINENUMBER 16 L3
ALOAD 1
ALOAD 2
ALOAD 3
INVOKEDYNAMIC makeConcatWithConstants(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/StringConcatFactory.makeConcatWithConstants(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
// arguments:
"\u0001\u0001\u0001"
]
ASTORE 4
which magically changes "the correct answer" to 4 objects since there is no intermediate StringBuilder involved.
*Let's dig a bit deeper.
12.5. Creation of New Class Instances
A new class instance may be implicitly created in the following situations:
Loading of a class or interface that contains a string literal (§3.10.5) may create a new String object to represent the literal. (This will not occur if a string denoting the same sequence of Unicode code points has previously been interned.)
In other words, when you start an application, there are already objects in the String pool. You barely know what they are and where they come from (unless you scan all loaded classes for all literals they contain).
The java.lang.String class will be undoubtedly loaded as an essential JVM class, meaning all its literals will be created and placed into the pool.
Let's take a randomly selected snippet from the source code of String, pick a couple of literals from it, put a breakpoint at the very beginning of our programme, and examine if the pool contains these literals.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
...
public String repeat(int count) {
// ...
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
" times will produce a String exceeding maximum size.");
}
}
...
}
They are there indeed.
As an interesting find, this IDEA's filtering has a side effect: the substrings I was looking for have been added to the pool as well. The pool size increased by one ("bytes String" was added) after I applied this.contains("bytes String").
Where does this leave us?
We have no idea whether "First" was created and interned before we call String str1 = "First";, so we can't state firmly that the line creates a new instance.
With the given information, the question cannot be definitely answered. As is stated in the JLS, §15.18.1:
... To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
This means that the answer depends at least on the concrete Java compiler used.
I think the best we can do is give an interval as answer:
a smart compiler may be able to infer that str1 to str3 are never used and fold the concatenation during compilation, such that only one String-object is created (the one referenced by str4)
The maximum sensible number of Strings created should be 5: one each for str1 to str3, one for tmp = str1 + str2 and one for str4 = tmp + str3.
So... my answer would be "something between one to five String-objects". As to the total number of objects created just for this operation... I do not know. This may also depend how exactly e.g. StringBuffer is implemented.
As an aside: I wonder what the reason behind asking such questions is. Normally, one does not need to care about those details.
Java 8 will likely create 5 objects:
3 for the 3 literals
1 StringBuilder
1 for the concatenated String
With Java 9 things changed though and String concatenation does not use StringBuilder anymore.
It should be 5:
three for the three literals (assigned to str1, str2 and str3)
one for str1 + str2
one for (result from the previous operation) + str3 (assigned to str4)
A conformant Java implementation can concatenate the strings any number of ways, at run time or at compile time, needing any number of run-time objects, including zero objects if it detects that the result is not needed at run time.
4 string object will be created in string constant pool. 3 for literals and 1 with concatenation.
if we use
String s1 = new String("one")
it will create two object one in constant pool and one in heap memory.
if we define :
String s1 = "one";
String s2 = new String("one");
it will create two object one in constant pool and one in heap memory.
Concatenation operation doesn't create those many String objects. It creates aStringBuilder and then appends the strings. So there may be 5 objects,
3 (variables) + 1 (sb) + 1 (Concatenated string).

Integer into textview [duplicate]

I'm working on a project where all conversions from int to String are done like this:
int i = 5;
String strI = "" + i;
I'm not familiar with Java.
Is this usual practice or is something wrong, as I suppose?
Normal ways would be Integer.toString(i) or String.valueOf(i).
The concatenation will work, but it is unconventional and could be a bad smell as it suggests the author doesn't know about the two methods above (what else might they not know?).
Java has special support for the + operator when used with strings (see the documentation) which translates the code you posted into:
StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(i);
String strI = sb.toString();
at compile-time. It's slightly less efficient (sb.append() ends up calling Integer.getChars(), which is what Integer.toString() would've done anyway), but it works.
To answer Grodriguez's comment: ** No, the compiler doesn't optimise out the empty string in this case - look:
simon#lucifer:~$ cat TestClass.java
public class TestClass {
public static void main(String[] args) {
int i = 5;
String strI = "" + i;
}
}
simon#lucifer:~$ javac TestClass.java && javap -c TestClass
Compiled from "TestClass.java"
public class TestClass extends java.lang.Object{
public TestClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
Initialise the StringBuilder:
2: new #2; //class java/lang/StringBuilder
5: dup
6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
Append the empty string:
9: ldc #4; //String
11: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
Append the integer:
14: iload_1
15: invokevirtual #6; //Method java/lang/StringBuilder.append:
(I)Ljava/lang/StringBuilder;
Extract the final string:
18: invokevirtual #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
21: astore_2
22: return
}
There's a proposal and ongoing work to change this behaviour, targetted for JDK 9.
It's acceptable, but I've never written anything like that. I'd prefer this:
String strI = Integer.toString(i);
It's not a good way.
When doing conversion from int to string, this should be used:
int i = 5;
String strI = String.valueOf(i);
It's not only the optimization1. I don't like
"" + i
because it does not express what I really want to do 2.
I don't want to append an integer to an (empty) string. I want to convert an integer to string:
Integer.toString(i)
Or, not my prefered, but still better than concatenation, get a string representation of an object (integer):
String.valueOf(i)
1. For code that is called very often, like in loops, optimization sure is also a point for not using concatenation.
2. this is not valid for use of real concatenation like in System.out.println("Index: " + i); or String id = "ID" + i;
A lot of introductory University courses seem to teach this style, for two reasons (in my experience):
It doesn’t require understanding of classes or methods. Usually, this is taught way before the word “class” is ever mentioned – nor even method calls. So using something like String.valueOf(…) would confuse students.
It is an illustration of “operator overloading” – in fact, this was sold to us as the idiomatic overloaded operator (small wonder here, since Java doesn’t allow custom operator overloading).
So it may either be born out of didactic necessity (although I’d argue that this is just bad teaching) or be used to illustrate a principle that’s otherwise quite hard to demonstrate in Java.
The expression
"" + i
leads to string conversion of i at runtime. The overall type of the expression is String. i is first converted to an Integer object (new Integer(i)), then String.valueOf(Object obj) is called. So it is equivalent to
"" + String.valueOf(new Integer(i));
Obviously, this is slightly less performant than just calling String.valueOf(new Integer(i)) which will produce the very same result.
The advantage of ""+i is that typing is easier/faster and some people might think, that it's easier to read. It is not a code smell as it does not indicate any deeper problem.
(Reference: JLS 15.8.1)
Personally, I don't see anything bad in this code.
It's pretty useful when you want to log an int value, and the logger just accepts a string. I would say such a conversion is convenient when you need to call a method accepting a String, but you have an int value.
As for the choice between Integer.toString or String.valueOf, it's all a matter of taste.
...And internally, the String.valueOf calls the Integer.toString method by the way. :)
The other way I am aware of is from the Integer class:
Integer.toString(int n);
Integer.toString(int n, int radix);
A concrete example (though I wouldn't think you need any):
String five = Integer.toString(5); // returns "5"
It also works for other primitive types, for instance Double.toString.
See here for more details.
This technique was taught in an undergraduate level introduction-to-Java class I took over a decade ago. However, I should note that, IIRC, we hadn't yet gotten to the String and Integer class methods.
The technique is simple and quick to type. If all I'm doing is printing something, I'll use it (for example, System.out.println("" + i);. However, I think it's not the best way to do a conversion, as it takes a second of thought to realize what's going on when it's being used this way. Also, if performance is a concern, it seems slower (more below, as well as in other answers).
Personally, I prefer Integer.toString(), as it is obvious what's happening. String.valueOf() would be my second choice, as it seems to be confusing (witness the comments after darioo's answer).
Just for grins :) I wrote up classes to test the three techniques: "" + i, Integer.toString, and String.ValueOf. Each test just converted the ints from 1 to 10000 to Strings. I then ran each through the Linux time command five times. Integer.toString() was slightly faster than String.valueOf() once, they tied three times, and String.valueOf() was faster once; however, the difference was never more than a couple of milliseconds.
The "" + i technique was slower than both on every test except one, when it was 1 millisecond faster than Integer.toString() and 1 millisecond slower than String.valueOf() (obviously on the same test where String.valueOf() was faster than Integer.toString()). While it was usually only a couple milliseconds slower, there was one test where it was about 50 milliseconds slower. YMMV.
There are three ways of converting to Strings
String string = "" + i;
String string = String.valueOf(i);
String string = Integer.toString(i);
There are various ways of converting to Strings:
StringBuilder string = string.append(i).toString();
String string = String.valueOf(i);
String string = Integer.toString(i);
It depends on how you want to use your String. This can help:
String total = Integer.toString(123) + Double.toString(456.789);
Mostly ditto on SimonJ. I really dislike the ""+i idiom. If you say String.valueOf(i), Java converts the integer to a string and returns the result. If you say ""+i, Java creates a StringBuilder object, appends an empty string to it, converts the integer to a string, appends this to the StringBuilder, then converts the StringBuilder to a String. That's a lot of extra steps. I suppose if you do it once in a big program, it's no big deal. But if you're doing this all the time, you're making the computer do a bunch of extra work and creating all these extra objects that then have to be cleaned up. I don't want to get fanatic about micro-optimization, but I don't want to be pointlessly wasteful either.
String strI = String.valueOf(i);
String string = Integer.toString(i);
Both of the ways are correct.
There are many way to convert an integer to a string:
1)
Integer.toString(10);
2)
String hundred = String.valueOf(100); // You can pass an int constant
int ten = 10;
String ten = String.valueOf(ten)
3)
String thousand = "" + 1000; // String concatenation
4)
String million = String.format("%d", 1000000)
Using "" + i is the shortest and simplest way to convert a number to a string. It is not the most efficient, but it is the clearest IMHO and that is usually more important. The simpler the code, the less likely you are to make a mistake.
Personally I think that "" + i does look as the original question poster states "smelly". I have used a lot of OO languages besides Java. If that syntax was intended to be appropriate then Java would just interpret the i alone without needing the "" as desired to be converted to a string and do it since the destination type is unambiguous and only a single value would be being supplied on the right. The other seems like a 'trick" to fool the compiler, bad mojo when different versions of Javac made by other manufacturers or from other platforms are considered if the code ever needs to be ported. Heck for my money it should like many other OOL's just take a Typecast: (String) i. winks
Given my way of learning and for ease of understanding such a construct when reading others code quickly I vote for the Integer.toString(i) method. Forgetting a ns or two in how Java implements things in the background vs. String.valueOf(i) this method feels right to me and says exactly what is happening: I have and Integer and I wish it converted to a String.
A good point made a couple times is perhaps just using StringBuilder up front is a good answer to building Strings mixed of text and ints or other objects since thats what will be used in the background anyways right?
Just my two cents thrown into the already well paid kitty of the answers to the Mans question... smiles
EDIT TO MY OWN ANSWER AFTER SOME REFLECTION:
Ok, Ok, I was thinking on this some more and String.valueOf(i) is also perfectly good as well it says: I want a String that represents the value of an Integer. lol, English is by far more difficult to parse then Java! But, I leave the rest of my answer/comment... I was always taught to use the lowest level of a method/function chain if possible and still maintains readablity so if String.valueOf calls Integer.toString then Why use a whole orange if your just gonna peel it anyways, Hmmm?
To clarify my comment about StringBuilder, I build a lot of strings with combos of mostly literal text and int's and they wind up being long and ugly with calls to the above mentioned routines imbedded between the +'s, so seems to me if those become SB objects anyways and the append method has overloads it might be cleaner to just go ahead and use it... So I guess I am up to 5 cents on this one now, eh? lol...
As already pointed out Integer.toString() or String.valueOf() are the way to go. I was curious and did a quick benchmark:
Integer.toString(i) and String.valueOf(i) are basically identical in performance, with Integer.toString(i) being a tiny bit faster. However i + "" is 1.7 times slower.
import java.util.Random;
public class Test {
public static void main(String[] args) {
long concat = 0;
long valueOf = 0;
long toString = 0;
int iterations = 10000;
int runs = 1000;
for(int i = 0; i < runs; i++) {
concat += concat(iterations);
valueOf += valueOf(iterations);
toString += to_String(iterations);
}
System.out.println("concat: " + concat/runs);
System.out.println("valueOf: " + valueOf/runs);
System.out.println("toString: " + toString/runs);
}
public static long concat(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = r.nextInt() + "";
}
return System.nanoTime() - start;
}
public static long valueOf(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = String.valueOf(r.nextInt());
}
return System.nanoTime() - start;
}
public static long to_String(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = Integer.toString(r.nextInt());
}
return System.nanoTime() - start;
}
}
Output:
concat: 1004109
valueOf: 590978
toString: 587236
use Integer.toString(tmpInt).trim();
Try simple typecasting
char c = (char) i;

Why use append() instead of + [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why to use StringBuffer in Java instead of the string concatenation operator
what is the advantage or aim of doing this
int a= 42
StringBuffer sb = new StringBuffer(40);
String s = sb.append("a = ").append(a).append("!").toString();
System.out.println(sb);
result > a = 42!
instead of
int a= 42
String s = "a = " + a + "!";
System.out.println(sb);
In your scenario, I'm not sure there is a difference b/c all of your "+" are on one line (which only creates a String once). In general, though, Strings are immutable objects and are not truly manipulated but rather created and discarded using StringBuffers.
So ultimately, you will have more efficient code if you use StringBuffers (and generally StringBuilders). If you google "String vs. StringBuffer vs. StringBuilder" you can find many articles detailing the statistics.
Efficiency. String concatenation in Java uses StringBuilders in the background anyway, so in some cases you can eke out a bit of efficiency by controlling that yourself.
Just run the code for 10000 time and measure the time. It should be obvious.
Some background-information: String is immutable while StringBuilder is not. So everytime you concatenate a String you have to copy an array.
PS: Sometimes the compiler optimizes things though. Maybe if you make your variable static final it would be just one String internally and no concatenation.
First of all, StringBuffer is synchronized, so you would typically use StringBuilder. + has been reimplemented to use StringBuilder a while ago.
Second, as #Riggy mentioned Java actually does optimize + as long as they occur in a single expression. But if you were to do:
String s = "";
s += a;
s += b;
s += c;
s += d;
Then the effective code would become:
String s ="";
s = new StringBuilder(s).append(a).toString();
s = new StringBuilder(s).append(b).toString();
s = new StringBuilder(s).append(c).toString();
s = new StringBuilder(s).append(d).toString();
which is suboptimal to
String s = new StringBuilder(s).append(a).append(b).append(c).append(d).toString();
Because of compiler optimizations, it may or may not make any difference in your app. You'll have to run comparison speed tests to see.
But before you obsess about performance, get the program working right. "Premature optimization is the root of all evil."

How do I convert from int to String?

I'm working on a project where all conversions from int to String are done like this:
int i = 5;
String strI = "" + i;
I'm not familiar with Java.
Is this usual practice or is something wrong, as I suppose?
Normal ways would be Integer.toString(i) or String.valueOf(i).
The concatenation will work, but it is unconventional and could be a bad smell as it suggests the author doesn't know about the two methods above (what else might they not know?).
Java has special support for the + operator when used with strings (see the documentation) which translates the code you posted into:
StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(i);
String strI = sb.toString();
at compile-time. It's slightly less efficient (sb.append() ends up calling Integer.getChars(), which is what Integer.toString() would've done anyway), but it works.
To answer Grodriguez's comment: ** No, the compiler doesn't optimise out the empty string in this case - look:
simon#lucifer:~$ cat TestClass.java
public class TestClass {
public static void main(String[] args) {
int i = 5;
String strI = "" + i;
}
}
simon#lucifer:~$ javac TestClass.java && javap -c TestClass
Compiled from "TestClass.java"
public class TestClass extends java.lang.Object{
public TestClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_5
1: istore_1
Initialise the StringBuilder:
2: new #2; //class java/lang/StringBuilder
5: dup
6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
Append the empty string:
9: ldc #4; //String
11: invokevirtual #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;
Append the integer:
14: iload_1
15: invokevirtual #6; //Method java/lang/StringBuilder.append:
(I)Ljava/lang/StringBuilder;
Extract the final string:
18: invokevirtual #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
21: astore_2
22: return
}
There's a proposal and ongoing work to change this behaviour, targetted for JDK 9.
It's acceptable, but I've never written anything like that. I'd prefer this:
String strI = Integer.toString(i);
It's not a good way.
When doing conversion from int to string, this should be used:
int i = 5;
String strI = String.valueOf(i);
It's not only the optimization1. I don't like
"" + i
because it does not express what I really want to do 2.
I don't want to append an integer to an (empty) string. I want to convert an integer to string:
Integer.toString(i)
Or, not my prefered, but still better than concatenation, get a string representation of an object (integer):
String.valueOf(i)
1. For code that is called very often, like in loops, optimization sure is also a point for not using concatenation.
2. this is not valid for use of real concatenation like in System.out.println("Index: " + i); or String id = "ID" + i;
A lot of introductory University courses seem to teach this style, for two reasons (in my experience):
It doesn’t require understanding of classes or methods. Usually, this is taught way before the word “class” is ever mentioned – nor even method calls. So using something like String.valueOf(…) would confuse students.
It is an illustration of “operator overloading” – in fact, this was sold to us as the idiomatic overloaded operator (small wonder here, since Java doesn’t allow custom operator overloading).
So it may either be born out of didactic necessity (although I’d argue that this is just bad teaching) or be used to illustrate a principle that’s otherwise quite hard to demonstrate in Java.
The expression
"" + i
leads to string conversion of i at runtime. The overall type of the expression is String. i is first converted to an Integer object (new Integer(i)), then String.valueOf(Object obj) is called. So it is equivalent to
"" + String.valueOf(new Integer(i));
Obviously, this is slightly less performant than just calling String.valueOf(new Integer(i)) which will produce the very same result.
The advantage of ""+i is that typing is easier/faster and some people might think, that it's easier to read. It is not a code smell as it does not indicate any deeper problem.
(Reference: JLS 15.8.1)
Personally, I don't see anything bad in this code.
It's pretty useful when you want to log an int value, and the logger just accepts a string. I would say such a conversion is convenient when you need to call a method accepting a String, but you have an int value.
As for the choice between Integer.toString or String.valueOf, it's all a matter of taste.
...And internally, the String.valueOf calls the Integer.toString method by the way. :)
The other way I am aware of is from the Integer class:
Integer.toString(int n);
Integer.toString(int n, int radix);
A concrete example (though I wouldn't think you need any):
String five = Integer.toString(5); // returns "5"
It also works for other primitive types, for instance Double.toString.
See here for more details.
This technique was taught in an undergraduate level introduction-to-Java class I took over a decade ago. However, I should note that, IIRC, we hadn't yet gotten to the String and Integer class methods.
The technique is simple and quick to type. If all I'm doing is printing something, I'll use it (for example, System.out.println("" + i);. However, I think it's not the best way to do a conversion, as it takes a second of thought to realize what's going on when it's being used this way. Also, if performance is a concern, it seems slower (more below, as well as in other answers).
Personally, I prefer Integer.toString(), as it is obvious what's happening. String.valueOf() would be my second choice, as it seems to be confusing (witness the comments after darioo's answer).
Just for grins :) I wrote up classes to test the three techniques: "" + i, Integer.toString, and String.ValueOf. Each test just converted the ints from 1 to 10000 to Strings. I then ran each through the Linux time command five times. Integer.toString() was slightly faster than String.valueOf() once, they tied three times, and String.valueOf() was faster once; however, the difference was never more than a couple of milliseconds.
The "" + i technique was slower than both on every test except one, when it was 1 millisecond faster than Integer.toString() and 1 millisecond slower than String.valueOf() (obviously on the same test where String.valueOf() was faster than Integer.toString()). While it was usually only a couple milliseconds slower, there was one test where it was about 50 milliseconds slower. YMMV.
There are three ways of converting to Strings
String string = "" + i;
String string = String.valueOf(i);
String string = Integer.toString(i);
There are various ways of converting to Strings:
StringBuilder string = string.append(i).toString();
String string = String.valueOf(i);
String string = Integer.toString(i);
It depends on how you want to use your String. This can help:
String total = Integer.toString(123) + Double.toString(456.789);
Mostly ditto on SimonJ. I really dislike the ""+i idiom. If you say String.valueOf(i), Java converts the integer to a string and returns the result. If you say ""+i, Java creates a StringBuilder object, appends an empty string to it, converts the integer to a string, appends this to the StringBuilder, then converts the StringBuilder to a String. That's a lot of extra steps. I suppose if you do it once in a big program, it's no big deal. But if you're doing this all the time, you're making the computer do a bunch of extra work and creating all these extra objects that then have to be cleaned up. I don't want to get fanatic about micro-optimization, but I don't want to be pointlessly wasteful either.
String strI = String.valueOf(i);
String string = Integer.toString(i);
Both of the ways are correct.
There are many way to convert an integer to a string:
1)
Integer.toString(10);
2)
String hundred = String.valueOf(100); // You can pass an int constant
int ten = 10;
String ten = String.valueOf(ten)
3)
String thousand = "" + 1000; // String concatenation
4)
String million = String.format("%d", 1000000)
Using "" + i is the shortest and simplest way to convert a number to a string. It is not the most efficient, but it is the clearest IMHO and that is usually more important. The simpler the code, the less likely you are to make a mistake.
Personally I think that "" + i does look as the original question poster states "smelly". I have used a lot of OO languages besides Java. If that syntax was intended to be appropriate then Java would just interpret the i alone without needing the "" as desired to be converted to a string and do it since the destination type is unambiguous and only a single value would be being supplied on the right. The other seems like a 'trick" to fool the compiler, bad mojo when different versions of Javac made by other manufacturers or from other platforms are considered if the code ever needs to be ported. Heck for my money it should like many other OOL's just take a Typecast: (String) i. winks
Given my way of learning and for ease of understanding such a construct when reading others code quickly I vote for the Integer.toString(i) method. Forgetting a ns or two in how Java implements things in the background vs. String.valueOf(i) this method feels right to me and says exactly what is happening: I have and Integer and I wish it converted to a String.
A good point made a couple times is perhaps just using StringBuilder up front is a good answer to building Strings mixed of text and ints or other objects since thats what will be used in the background anyways right?
Just my two cents thrown into the already well paid kitty of the answers to the Mans question... smiles
EDIT TO MY OWN ANSWER AFTER SOME REFLECTION:
Ok, Ok, I was thinking on this some more and String.valueOf(i) is also perfectly good as well it says: I want a String that represents the value of an Integer. lol, English is by far more difficult to parse then Java! But, I leave the rest of my answer/comment... I was always taught to use the lowest level of a method/function chain if possible and still maintains readablity so if String.valueOf calls Integer.toString then Why use a whole orange if your just gonna peel it anyways, Hmmm?
To clarify my comment about StringBuilder, I build a lot of strings with combos of mostly literal text and int's and they wind up being long and ugly with calls to the above mentioned routines imbedded between the +'s, so seems to me if those become SB objects anyways and the append method has overloads it might be cleaner to just go ahead and use it... So I guess I am up to 5 cents on this one now, eh? lol...
As already pointed out Integer.toString() or String.valueOf() are the way to go. I was curious and did a quick benchmark:
Integer.toString(i) and String.valueOf(i) are basically identical in performance, with Integer.toString(i) being a tiny bit faster. However i + "" is 1.7 times slower.
import java.util.Random;
public class Test {
public static void main(String[] args) {
long concat = 0;
long valueOf = 0;
long toString = 0;
int iterations = 10000;
int runs = 1000;
for(int i = 0; i < runs; i++) {
concat += concat(iterations);
valueOf += valueOf(iterations);
toString += to_String(iterations);
}
System.out.println("concat: " + concat/runs);
System.out.println("valueOf: " + valueOf/runs);
System.out.println("toString: " + toString/runs);
}
public static long concat(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = r.nextInt() + "";
}
return System.nanoTime() - start;
}
public static long valueOf(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = String.valueOf(r.nextInt());
}
return System.nanoTime() - start;
}
public static long to_String(int iterations) {
Random r = new Random(0);
long start = System.nanoTime();
for(int i = 0; i < iterations; i++) {
String s = Integer.toString(r.nextInt());
}
return System.nanoTime() - start;
}
}
Output:
concat: 1004109
valueOf: 590978
toString: 587236
use Integer.toString(tmpInt).trim();
Try simple typecasting
char c = (char) i;

String concatenation: concat() vs "+" operator

Assuming String a and b:
a += b
a = a.concat(b)
Under the hood, are they the same thing?
Here is concat decompiled as reference. I'd like to be able to decompile the + operator as well to see what that 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);
}
}
No, not quite.
Firstly, there's a slight difference in semantics. If a is null, then a.concat(b) throws a NullPointerException but a+=b will treat the original value of a as if it were null. Furthermore, the concat() method only accepts String values while the + operator will silently convert the argument to a String (using the toString() method for objects). So the concat() method is more strict in what it accepts.
To look under the hood, write a simple class with a += b;
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
Now disassemble with javap -c (included in the Sun JDK). You should see a listing including:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
So, a += b is the equivalent of
a = new StringBuilder()
.append(a)
.append(b)
.toString();
The concat method should be faster. However, with more strings the StringBuilder method wins, at least in terms of performance.
The source code of String and StringBuilder (and its package-private base class) is available in src.zip of the Sun JDK. You can see that you are building up a char array (resizing as necessary) and then throwing it away when you create the final String. In practice memory allocation is surprisingly fast.
Update: As Pawel Adamski notes, performance has changed in more recent HotSpot. javac still produces exactly the same code, but the bytecode compiler cheats. Simple testing entirely fails because the entire body of code is thrown away. Summing System.identityHashCode (not String.hashCode) shows the StringBuffer code has a slight advantage. Subject to change when the next update is released, or if you use a different JVM. From #lukaseder, a list of HotSpot JVM intrinsics.
Niyaz is correct, but it's also worth noting that the special + operator can be converted into something more efficient by the Java compiler. Java has a StringBuilder class which represents a non-thread-safe, mutable String. When performing a bunch of String concatenations, the Java compiler silently converts
String a = b + c + d;
into
String a = new StringBuilder(b).append(c).append(d).toString();
which for large strings is significantly more efficient. As far as I know, this does not happen when you use the concat method.
However, the concat method is more efficient when concatenating an empty String onto an existing String. In this case, the JVM does not need to create a new String object and can simply return the existing one. See the concat documentation to confirm this.
So if you're super-concerned about efficiency then you should use the concat method when concatenating possibly-empty Strings, and use + otherwise. However, the performance difference should be negligible and you probably shouldn't ever worry about this.
I ran a similar test as #marcio but with the following loop instead:
String c = a;
for (long i = 0; i < 100000L; i++) {
c = c.concat(b); // make sure javac cannot skip the loop
// using c += b for the alternative
}
Just for good measure, I threw in StringBuilder.append() as well. Each test was run 10 times, with 100k reps for each run. Here are the results:
StringBuilder wins hands down. The clock time result was 0 for most the runs, and the longest took 16ms.
a += b takes about 40000ms (40s) for each run.
concat only requires 10000ms (10s) per run.
I haven't decompiled the class to see the internals or run it through profiler yet, but I suspect a += b spends much of the time creating new objects of StringBuilder and then converting them back to String.
Most answers here are from 2008. It looks that things have changed over the time. My latest benchmarks made with JMH shows that on Java 8 + is around two times faster than concat.
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))));
}
}
Results:
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
Tom is correct in describing exactly what the + operator does. It creates a temporary StringBuilder, appends the parts, and finishes with toString().
However, all of the answers so far are ignoring the effects of HotSpot runtime optimizations. Specifically, these temporary operations are recognized as a common pattern and are replaced with more efficient machine code at run-time.
#marcio: You've created a micro-benchmark; with modern JVM's this is not a valid way to profile code.
The reason run-time optimization matters is that many of these differences in code -- even including object-creation -- are completely different once HotSpot gets going. The only way to know for sure is profiling your code in situ.
Finally, all of these methods are in fact incredibly fast. This might be a case of premature optimization. If you have code that concatenates strings a lot, the way to get maximum speed probably has nothing to do with which operators you choose and instead the algorithm you're using!
How about some simple testing? Used the code below:
long start = System.currentTimeMillis();
String a = "a";
String b = "b";
for (int i = 0; i < 10000000; i++) { //ten million times
String c = a.concat(b);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
The "a + b" version executed in 2500ms.
The a.concat(b) executed in 1200ms.
Tested several times. The concat() version execution took half of the time on average.
This result surprised me because the concat() method always creates a new string (it returns a "new String(result)". It's well known that:
String a = new String("a") // more than 20 times slower than String a = "a"
Why wasn't the compiler capable of optimize the string creation in "a + b" code, knowing the it always resulted in the same string? It could avoid a new string creation.
If you don't believe the statement above, test for your self.
Basically, there are two important differences between + and the concat method.
If you are using the concat method then you would only be able to concatenate strings while in case of the + operator, you can also concatenate the string with 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 have to provide two strings mandatory.
The second and main difference between + and concat is that:
Case 1:
Suppose I concat the same strings with concat operator in this way
String s="I";
String s1=s.concat("am").concat("good").concat("boy");
System.out.println(s1);
In this case total number of objects created in the pool are 7 like this:
I
am
good
boy
Iam
Iamgood
Iamgoodboy
Case 2:
Now I am going to concatinate the same strings via + operator
String s="I"+"am"+"good"+"boy";
System.out.println(s);
In the above case total number of objects created are only 5.
Actually when we concatinate the strings via + operator then it maintains 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);
In this way it will create only five objects.
So guys these are the basic differences between + and the concat method.
Enjoy :)
For the sake of completeness, I wanted to add that the definition of the '+' operator can be found in the JLS SE8 15.18.1:
If only one operand expression is of type String, then string
conversion (§5.1.11) is performed on the other operand to produce a
string at run time.
The result of string concatenation is a reference to a String object
that is the concatenation of the two operand strings. The characters
of the left-hand operand precede the characters of the right-hand
operand in the newly created string.
The String object is newly created (§12.5) unless the expression is a
constant expression (§15.28)
About the implementation the JLS says the following:
An implementation may choose to perform conversion and concatenation
in one step to avoid creating and then discarding an intermediate
String object. To increase the performance of repeated string
concatenation, a Java compiler may use the StringBuffer class or a
similar technique to reduce the number of intermediate String objects
that are created by evaluation of an expression.
For primitive types, an implementation may also optimize away the
creation of a wrapper object by converting directly from a primitive
type to a string.
So judging from the 'a Java compiler may use the StringBuffer class or a similar technique to reduce', different compilers could produce different byte-code.
The + operator can work between a string and a string, char, integer, double or float data type value. It just converts the value to its string representation before concatenation.
The concat operator can only be done on and with strings. It checks for data type compatibility and throws an error, if they don't match.
Except this, the code you provided does the same stuff.
I don't think so.
a.concat(b) is implemented in String and I think the implementation didn't change much since early java machines. The + operation implementation depends on Java version and compiler. Currently + is implemented using StringBuffer to make the operation as fast as possible. Maybe in the future, this will change. In earlier versions of java + operation on Strings was much slower as it produced intermediate results.
I guess that += is implemented using + and similarly optimized.
When using +, the speed decreases as the string's length increases, but when using concat, the speed is more stable, and the best option is using the StringBuilder class which has stable speed in order to do that.
I guess you can understand why. But the totally best way for creating long strings is using StringBuilder() and append(), either speed will be unacceptable.
Note that s.concat("hello"); would result in a NullPointereException when s is null. In Java, the behavior of the + operator is usually determined by the left operand:
System.out.println(3 + 'a'); //100
However, Strings are an exception. If either operand is a String, the result is expected to be a String. This is the reason null is converted into "null", even though you might expect a RuntimeException.

Categories