String builder vs string concatenation [duplicate] - java

This question already has answers here:
StringBuilder vs String concatenation in toString() in Java
(20 answers)
Closed 6 years ago.
What is the benefit and trade-off of using a string builder over pure string concatenation?
new StringBuilder(32).append(str1)
.append(" test: ")
.append(val)
.append(" is changed")
.toString();
vs say
str1 + " test: " + val + " is changed".
str1 is a random 10 character string.
str2 is a random 8 character string.

In your particular example, none because the compiler internally uses StringBuilders to do String concatenation. If the concatenation occurred in a loop, however, the compiler could create several StringBuilder and String objects. For example:
String s= "" ;
for(int i= 0 ; i < 10 ; i++ )
s+= "a" ;
Each time line 3 above is executed, a new StringBuilder object is created, the contents of s appended, "a" appended, and then the StringBuilder is converted into a String to be assigned back to s. A total of 10 StringBuilders and 10 Strings.
Conversely, in
StringBuilder sb= new StringBuilder() ;
for(int i= 0 ; i < 10 ; i++ )
sb.append( "a" );
String s= sb.toString() ;
Only 1 StringBuilder and 1 String are created.
The main reason for this is that the compiler could not be smart enough to understand that the first loop is equivalent to the second and generate more efficient (byte) code. In more complex cases, it's impossible even for the smartest compiler to know. If you absolutely need this optimization, you have to introduce it manually by using StringBuilders explicitly.

The quick answer is the performance:
when you are using native String classes it operates immutable strings, which means when you are writing
String line = "java";
String sufix = " is awesome";
line = line + sufix;
it will create two strings "java" and " is awesome", than create a new third string "java is awesome" from previous two ("java" and "is awesome") which later are likely to be deleted by a garbage collector (because they are no more used in app). That is a slow solution.
More faster solution is an appliance of StringBuffer class which through the smart algorightms that provide a buffer (that is obvious from its name) for merging strings and as a result would not remove the initial string during the concatenation process.
In case you are writing single thread-application (no concurrancy issues during which multiple threads access same object) it is better to apply StringBuilder which has even faster performance than the initial StringBuffer class.

Related

Joining string array together, from certain argument, into a string? [duplicate]

This question already has answers here:
What's the best way to build a string of delimited items in Java?
(37 answers)
Closed 6 years ago.
Here is my String array containing the following:
"message" "player" "how" "are" "you"
I am wanting to join the "how" "are" "you" part of the String[] and I am currently doing the following:
String msg = "";
for (int i = 2; i < args.length; i++)
{
msg = msg + args[i] + " ";
}
Util.messagePlayer(player, msg);
So my question is, is there a better/more efficient way of doing this?
Yes, there is a better way, everytime you are iterating that array, new String objects are getting created(because Strings are immutable), however this one is a short String, so the efficiency loss is not that considerable,still try to use StringBuilder instead
StringBuilder msg = new StringBuilder();
for (int i = 2; i < args.length; i++)
{
msg.append(args[i] + " ");
}
Util.messagePlayer(player, msg.toString);
For complete details, StringBuilder vs String concatenation in toString() in Java
String objects are immutable ones in Java, hence every time you concatenate two strings, you are creating a new Object this is costly.
Instead, you can use a StringBuilder.
More about how to use it is well described here:
Correct way to use StringBuilder

How can I efficiently use StringBuilder?

In the past, I've always used printf to format printing to the console but the assignment I currently have (creating an invoice report) wants us to use StringBuilder, but I have no idea how to do so without simply using " " for every gap needed. For example... I'm supposed to print this out
Invoice Customer Salesperson Subtotal Fees Taxes Discount Total
INV001 Company Eccleston, Chris $ 2357.60 $ 40.00 $ 190.19 $ -282.91 $ 2304.88
But I don't know how to get everything to line up using the StringBuilder. Any advice?
StringBuilder aims to reduce the overhead associated with creating strings.
As you may or may not know, strings are immutable. What this means that something like
String a = "foo";
String b = "bar";
String c = a + b;
String d = c + c;
creates a new string for each line. If all we are concerned about is the final string d, the line with string c is wasting space because it creates a new String object when we don't need it.
String builder simply delays actually building the String object until you call .toString(). At that point, it converts an internal char[] to an actual string.
Let's take another example.
String foo() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++)
sb.append(i);
return sb.toString();
}
Here, we only create one string. StringBuilder will keep track of the chars you have added to your string in its internal char[] value. Note that value.length will generally be larger than the total chars you have added to your StringBuilder, but value might run out of room for what you're appending if the string you are building gets too big. When that happens, it'll resize, which just means replacing value with a larger char[], and copying over the old values to the new array, along with the chars of whatever you appended.
Finally, when you call sb.toString(), the StringBuilder will call a String constructor that takes an argument of a char[].
That means only one String object was created, and we only needed enough memory for our char[] and to resize it.
Compare with the following:
String foo() {
String toReturn = "";
for (int i = 0; i < 100; i++)
toReturn += "" + i;
toReturn;
}
Here, we have 101 string objects created (maybe more, I'm unsure). We only needed one though! This means that at every call, we're disposing the original string toReturn represented, and creating another string.
With a large string, especially, this is very expensive, because at every call you need to first acquire as much memory as the new string needs, and dispose of as much memory as the old string had. It's not a big deal when things are kept short, but when you're working with entire files this can easily become a problem.
In a nutshell: if you're working appending / removing information before finalizing an output: use a StringBuilder. If your strings are very short, I think it is OK to just concatenate normally for convenience, but this is up to you to define what "short" is.

Why string concatenation takes so long time? [duplicate]

This question already has answers here:
StringBuilder vs String concatenation in toString() in Java
(20 answers)
Closed 7 years ago.
I am concatenating a String in a loop but it takes ages, why is that?
for (String object : jsonData) {
counter++;
finalJsonDataStr += object;
}
Variable object is a piece of JSON, up to 70 chars and the loop goes approx 50k times.
I understand some people advice StringBuffer or StringBuilder but this link says, it has no performance improvements: StringBuilder vs String concatenation in toString() in Java
Use a String Builder to append to strings.
When you concatenate, Java is actually creating a new String with the results of the concatenation.
Do it multiple times and you are creating gazillion of strings for nothing.
Try:
StringBuilder sb = new StringBuilder();
for (String object : jsonData) {
counter++;
sb.append(object.toString()); //this does the concatenation internally
//but is very efficient
}
finalJsonDataStr = sb.toString(); //this gives you back the whole string
Remark:
When you do stuff like
myString = "hello " + someStringVariable + " World!" + " My name is " + name;
The compiler is smart enough to replace all that with a single StringBuilder, like:
myString = new StringBuilder("hello ")
.append(someStringVariable)
.append(" World!")
.append(" My name is ")
.append(name).toString();
But for some reason I don't know, it doesn't do it when the concatenation happens inside a loop.
You should use a StringBuffer or a StringBuilder.
When you add Strings with plus, a StringBuilder is created, strings are concatenated and a new String is return with toString() method of the StringBuilder. So image this object creation and string manipulation 50k times. It's much better if you instantiate only one StringBuilder yourself and just append strings...
This answer could be of use to you: concatenation operator (+) vs concat()
Before going to the actual problem, see how internal concatenation works.
String testString ="str"+"ingcon"+"catenation";
If we print the above declared String to console and see, the result is stringconcatenation.Which is correct and the + works fine. Here is out actual question, how does that + symbol did the magic ? ? Is it not a normal mathematical addition of Strings. The below code snippet shows how that code with + actually converts.
StringBuilder compilerGeneratedBuilder = new StringBuilder();
compilerGeneratedBuilder.append("str");
compilerGeneratedBuilder.append("ingcon");
compilerGeneratedBuilder.append("catenation");
String finalString = compilerGeneratedBuilder.toString();
More .....
50K times loop is a descent performance blocker to consider.
In such cases use StringBuilder with append method. Cause concat (+) create a new object every time a new String Builder object. That leads to 50k objects creations.
With single StringBuilder and append method, you can save the time of Objection creation as well as the memory too.

Concatenation of two Java strings [duplicate]

This question already has answers here:
Comparing strings with == which are declared final in Java
(6 answers)
a confusion about java String literal pool and String's concatenation
(4 answers)
Closed 8 years ago.
When I write the following code
int a = "Java";
the java compiler displays the following error :
cannot convert from String to int
So the constant Java is considered as an object derived from
String class.
- Is it true that each list of characters contained between "" is considered as an object derived from String class?
When I try to have concatenation of two strings I used the two
following examples:
String ch1 = "Java " ;
String ch2 = "is cool";
String ch3 = ch1 + ch2;
after I used the command javap -c on my compiled class I found
that the compiler use an instance of StringBuilder to append the
two strings.
but with the other example:
String ch = "Java " + "is cool";
Although the two constants "Java " and "is cool" are both two objects derived from String
class, the compiler doesn't use an instance of StringBuilder to
append the two strings.
- So what's the approach used in the second example?
From here.
'+' creates a new String object every time it concatenates something, except when the concatenation is done at compile time.
While this is not a reputable source, from what I remember from my textbooks this sounds correct. So basically, applying this to your code:
String ch = "Java " + "is cool";
Would be handled at compile time since you've defined two constants and concatenated them together, which implies that the result is also in fact a constant and thus can be treated as such and calculated at compile time. It would be interesting to see if you compiled that code then decompiled to see how that statement would read, I'd imagine it may read:
String ch = "Java is cool";
As for the other statement:
String ch1 = "Java " ;
String ch2 = "is cool";
String ch3 = ch1 + ch2;
Since ch3 is calculated from ch1 and ch2, it is done at runtime since ch1 and ch2 are variables instead of constants.
As for your first question, I can't find any references exactly, but from what I remember yes the "" implies a string, just like '' implies a character. I'm not exactly sure what you're trying to do with that statement, but I would imagine you could convert your string into a char array and then cast it to an int array.
Not sure what your second question is, but for your first question:
"Java" is a string and you're trying to store it as an int type. It is not an integer. The variable a needs to be of type string.
String a = "Java ";
In the first example you have created 2 strings vars, ch1 and ch2 that could be used in other parts of the code so... when you init ch3 a new string in memory is created with the content of both vars (here is where StringBuilder do the work). This is needed because you can change the value of ch2 and ch3 will be not changed.
In the second example both strings are final and never used again further in the code, so Java simply create a unique String "Java is cool".
I don't know if I've explained it well.
When you do the following line
String ch1 = "Java " ;
String ch2 = "is cool";
String ch3 = ch1 + ch2;
Both ch1 and ch2 are literal and the Compiler would create String instance using StringBuilder . In the earlier days ( when compiler is not smart enough to do this) we would be wasting memory for each execution by concat operation
but when you use this
String ch = "Java " + "is cool";
Compiler understood that String Literal "Java " + "is cool" cannot be modified at any time. So the compilers would translate this into
String ch = "Java is cool";
as byte code. and only one String literal would create run time.

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."

Categories