String initialisation and concatenation in java - java

In my application everything is working fine but I want to increase performance and optimize my code.
which of these two is better for
1.initialisation
String str1=new String("Hello");
String str2="Hello";
2.concatenation
System.out.println(s1 + s2);
System.out.println(new StringBuffer(S1).append(s2));

First of all, do not increase performance and optimize your code, unless you first profiled your application and realized a very good reason to do so.
Second, for initialization of a String variable it is better to not use the String constructor. Using a constant string (as done for str2), Java can pull the String object out of a String pool.
Third, do not use StringBuffer for concatenation. Use StringBuilder instead. StringBuffer's methods are synchronized, which slows down your application significantly. Indeed, your two kinds of concatenation are nearly equal, as all modern compilers create byte code, that uses a StringBuilder for expressions like "s1 + s2".

For the initialization it is better the second approach :
String str2="Hello";
because in this way you can make use of the Java String Pool and avoid not needed allocations .
For concatenation the second approach would be the best bet when you have to perform a lot of string concatenation, to concatenate only two string, the first approach is simpler and enough...

Use
String str2="Hello";
for string initialization, because if "Hello" string is avaialable in JVM string pool then new memory object will not be created
Two other suggestions:
If you are manipulating string then use StringBuffer as it does not create new strings with each string manipulation as String class does.
If your application is thread safe then use StringBuilder to avoid unnecessary overhead of StringBuffer, which is designed for multi-threaded operations.

For initialization it is better to use the second version because that will enable the JVM the String "interned", that means it can always return the same String-instance every time that constant is used. The first version will always create a new String object when this code is encountered, thus creating extra memory-consumption.
For concatenation, in simple cases like your example the compiler will do optimization so both ways will end up essentially the same. For more complicated String-concatenations it is better to either use a Stringbuffer or a StringBuilder. Use of a StringBuffer is necessary when the StringBuilder is accessed from multiple threads, in other cases StringBuilder will give better performance because it won't do any locking.

In initialization
String str2="Hello";
is better approach
In concatenation
System.out.println(s1 + s2);
is better approach.
Beacuse both they use String Constant pool which is ment for performance improvement

System.out.println(s1 + s2);
System.out.println(new StringBuffer(S1).append(s2));
From those two above, first would be faster, because + is translated into StringBuilder, that is faster compared to StringBuffer
And anyway... fastest, but some kind nasty-looking, way of adding 2 Strings is to use string1.concat(string2) method, that does not need to produce new object of Stringbuilder of Buffer.
You can also reuse the same StringBuilder for adding many Strings, by reseting it with sb.setLength(0) after each fully-added-String
:
StringBuilder sb = new StringBuilder();
String done1 = sb.append("1").append("2").append("3").toString();
sb.setLength(0);
String done2 = sb.append("4").append("5").append("6").toString();
sb.setLength(0);
String done3 = sb.append("7").append("8").append("9").toString();
sb.setLength(0);
System.out.println(done1);
System.out.println(done2);
System.out.println(done3);
Lastly, inside loops, you should always use StringBuilder/Buffer explicitly, ignoring that magic about using +. Because you would end up with many temporally StringBuilder objects, instead of only one that you should explicitly create before loop.
//not:
String result = "";
for (int i = 0; i < 20; i++) {
result += i; // this would create new StringBuilding in bytecode
}
System.out.println(result);
//but:
StringBuilder result1 = new StringBuilder();
for (int i = 0; i < 20; i++) {
result1.append(i);
}
System.out.println(result1);

in initialization Second approach is good as it only creates one object
String str1=new String("Hello");
Here two objects are getting created one in heap and other one in String pool
String str2="Hello";
here only one object is getting created in String pool.
System.out.println(s1 + s2);
Here total three objects are there s1 s2 and s1+s2 all in String pool
System.out.println(new StringBuffer(S1).append(s2));
Here only one object in head area which is S1+S2 so in both cases second approach is good

1)Go for literals,String literals are stored in a common pool. This facilitates sharing of storage for strings with the same contents to conserve storage. String objects allocated via new operator are stored in the heap, and there is no sharing of storage for the same contents.
other than
Literals are reader friendly ,than using constructors.
2)Go for StringBuilder instead of + which avoid's multiple string object creations.
For the second point ,with 2 to 3 appends or +'s ,there is no much difference.But when you are appending a 50 strings to one another,It matters'.
Might helpful :
How can a string be initialized using " "?
String literal behavioral specification.
Most of the memory related issues maintains/resolves by java itself.I belive in clean and readable code unless it's showing major impact.

Don't optimize before you REALLY need this.
If you optimize when it is not needed you decrease readability and waste time. It is really rare case that string initialization will cause performance problems for you.

Related

Java HeapDump Analysis: String or StringBuilder, what should be used?

In my application there was a heap dump and surprisingly heap retained by char[] was around 700MB, which was strange (at least for me). At the same time String had only 150MB.
In my application, I have only used StringBuilder (using default StringBuilder constructor) and tried to avoid using String as we were appending data.
My question here is: Should we always go for StringBuilder? And if yes, how can we reduce the heap retained by it?
Yes, always go for StringBuilder when building strings - it's the most efficient, but still convenient, way of concatenating strings.
It sounds like there are lots of StringBuilders hanging around waiting to be garbage collected. However, to reduce heap usage, you can safely reuse your StringBuilders even though they are not threadsafe by using one StringBuilder per thread via Threadlocal:
private static final ThreadLocal<StringBuilder> LOCAL_STRING_BUILDER =
ThreadLocal.withInitial(StringBuilder::new);
Example usage:
public String logMessage() {
StringBuilder sb = LOCAL_STRING_BUILDER.get();
sb.setLength(0); // Only resets the pointer to start. Doesn't affect the backing array
sb.append("foo=").append(myField); //etc
return sb.toString();
}
You will only ever have at most as many StringBuilders as there are threads, which won't be that many (maybe 10's - 100's).
FYI StringBuilder is used when concatenating strings manually anyway; this line of source:
String str3 = str1 + str2;
gets compiled as if it were:
String str3 = new StringBuilder().append(str1).append(str2).toString();
Possibly you can use StringInterner which takes a StringBuilder to avoid creating objects needlessly.You first populate a recycled StringBuilder with the text and if a String matching that text is in the interner, that String is returned (or a toString() of the StringBuilder is.) The benefit is that you only create objects (and no more than needed) when you see a new String (or at least one not in the array) This can get a 80% to 99% hit rate and reduce memory consumption (and garbage) dramatically when loading many strings of data.
Code:
https://github.com/OpenHFT/Java-Lang/blob/master/lang/src/main/java/net/openhft/lang/pool/StringInterner.java

Is chain of StringBuilder.append more efficient than string concatenation?

According to Netbeans hint named Use chain of .append methods instead of string concatenation
Looks for string concatenation in the parameter of an invocation of the append method of StringBuilder or StringBuffer.
Is StringBuilder.append() really more efficient than strings concatenation?
Code sample
StringBuilder sb = new StringBuilder();
sb.append(filename + "/");
vs.
StringBuilder sb = new StringBuilder();
sb.append(filename).append("/");
You have to balance readability with functionality.
Let's say you have the following:
String str = "foo";
str += "bar";
if(baz) str += "baz";
This will create 2 string builders (where you only need 1, really) plus an additional string object for the interim. You would be more efficient if you went:
StringBuilder strBuilder = new StringBuilder("foo");
strBuilder.append("bar");
if(baz) strBuilder.append("baz");
String str = strBuilder.toString();
But as a matter of style, I think the first one looks just fine. The performance benefit of a single object creation seems very minimal to me. Now, if instead of 3 strings, you had 10, or 20, or 100, I would say the performance outweighs the style. If it was in a loop, for sure I'd use the string builder, but I think just a couple strings is fine to do the 'sloppy' way to make the code look cleaner. But... this has a very dangerous trap lurking in it! Read on below (pause to build suspense... dun dun dunnnn)
There are those who say to always use the explicit string builder. One rationale is that your code will continue to grow, and it will usually do so in the same manner as it is already (i.e. they won't take the time to refactor.) So you end up with those 10 or 20 statements each creating their own builder when you don't need to. So to prevent this from the start, they say always use an explicit builder.
So while in your example, it's not going to be particularly faster, when someone in the future decides they want a file extension on the end, or something like that, if they continue to use string concatenation instead of a StringBuilder, they're going to run into performance problems eventually.
We also need to think about the future. Let's say you were making Java code back in JDK 1.1 and you had the following method:
public String concat(String s1, String s2, String s3) {
return s1 + s2 + s3;
}
At that time, it would have been slow because StringBuilder didn't exist.
Then in JDK 1.3 you decided to make it faster by using StringBuffer (StringBuilder still doesn't exist yet). You do this:
public String concat(String s1, String s2, String s3) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
sb.append(s3);
return sb.toString();
}
It gets a lot faster. Awesome!
Now JDK 1.5 comes out, and with it comes StringBuilder (which is faster than StringBuffer) and the automatic transation of
return s1 + s2 + s3;
to
return new StringBuilder().append(s1).append(s2).append(s3).toString();
But you don't get this performance benefit because you're using StringBuffer explicitly. So by being smart, you have caused a performance hit when Java got smarter than you. So you have to keep in mind that there are things out there you won't think of.
Well, your first example is essentially translated by the compiler into something along the lines:
StringBuilder sb = new StringBuilder();
sb.append(new StringBuilder().append(filename).append("/").toString());
so yes, there is a certain inefficiency here. However, whether it really matters in your program is a different question. Aside from being questionable style (hint: subjective), it usually only matters, if you are doing this in a tight loop.
None of the answers so far explicitly address the specific case that hint is for. It's not saying to always use StringBuilder#append instead of concatenation. But, if you're already using a StringBuilder, it doesn't make sense to mix in concatenation, because it creates a redundant StringBuilder (See Dirk's answer) and an unnecessary temporary String instance.
Several answers already discuss why the suggested way is more efficient, but the main point is, if you already have a StringBuilder instance, just call append on it. It's just as readable (in my opinion, and apparently whoever wrote the NetBeans hint) since you're calling append anyway, and it's a little more efficient.
Theoretically, yes. Because String objects are immutable: once constructed they cannot be changed anymore. So using "+" (concatenation) basically creates a new object each time.
Practically no. The compiler is clever enough to replace all your "+" with StringBuilder appendings.
For a more detailed explanation:
http://kaioa.com/node/59
PS: Netbeans??? Come on!
A concat of two strings is faster using this function.
However, if you have multiple strings or different data type, you should use a StringBuilder either explicitly or implicitly. Using a + with Strings is using a StringBuilder implicitly.
It's only more efficient if you are using lots of concatenation and really long strings. For general-use, such as creating a filename in your example, any string concatenation is just fine and more readable.
At any rate, this part of your application is unlikely to be the performance bottleneck.

When should we change a String to a Stringbuilder?

In an application a String is a often used data type. What we know, is that the mutation of a String uses lots of memory. So what we can do is to use a StringBuilder/StringBuffer.
But at what point should we change to StringBuilder?
And what should we do, when we have to split it or to remplace characters in there?
eg:
//original:
String[] split = string.split("?");
//better? :
String[] split = stringBuilder.toString().split("?);
or
//original:
String replacedString = string.replace("l","st");
//better? :
String replacedString = stringBuilder.toString().replace("l","st");
//or
StringBuilder replacedStringBuilder = new StringBuilder(stringBuilder.toString().replace("l","st);
In your examples, there are no benefits in using a StringBuilder, since you use the toString method to create an immutable String out of your StringBuilder.
You should only copy the contents of a StringBuilder into a String after you are done appending it (or modifying it in some other way).
The problem with Java's StringBuilder is that it lacks some methods you get when using a plain string (check this thread, for example: How to implement StringBuilder.replace(String, String)).
What we know, is that a String uses lots of memory.
Actually, to be precise, a String uses less memory than a StringBuilder with equivalent contents. A StringBuilder class has some additional constant overhead, and usually has a preallocated buffer to store more data than needed at any given moment (to reduce allocations). The issue with Strings is that they are immutable, which means Java needs to create a new instance whenever you need to change its contents.
To conclude, StringBuilder is not designed for the operations you mentioned (split and replace), and it won't yield much better performance in any case. A split method cannot benefit from StringBuilder's mutability, since it creates an array of immutable strings as its output anyway. A replace method still needs to iterate through the entire string, and do a lot of copying if replaced string is not the same size as the searched one.
If you need to do a lot of appending, then go for a StringBuilder. Since it uses a "mutable" array of characters under the hood, adding data to the end will be especially efficient.
This article compares the performance of several StringBuilder and String methods (although I would take the Concatenation part with reserve, because it doesn't mention dynamic string appending at all and concentrates on a single Join operation only).
What we know, is that the mutation of a String uses lots of memory.
That is incorrect. Strings cannot be mutated. They are immutable.
What you are actually talking about is building a String from other strings. That can use a lot more memory than is necessary, but it depends how you build the string.
So what we can do is to use a StringBuilder/StringBuffer.
Using a StringBuilder will help in some circumstances:
String res = "";
for (String s : ...) {
res = res + s;
}
(If the loop iterates many times then optimizing the above to use a StringBuilder could be worthwhile.)
But in other circumstances it is a waste of time:
String res = s1 + s2 + s3 + s4 + s5;
(It is a waste of time to optimize the above to use a StringBuilder because the Java compiler will automatically translate the expression into code that creates and uses a StringBuilder.)
You should only ever use a StringBuffer instead of a StringBuilder when the string needs to be accessed and/or updated by more than one thread; i.e. when it needs to be thread-safe.
But at what point should we change to StringBuilder?
The simple answer is to only do it when the profiler tells you that you have a performance problem in your string handling / processing.
Generally speaking, StringBuilders are used for building strings rather as the primary representation of the strings.
And what should we do, when we have to split it or to replace characters in there?
Then you have to review your decision to use a StringBuilder / StringBuffer as your primary representation at that point. And if it is still warranted you have to figure out how to do the operation using the API you have chosen. (This may entail converting to a String, performing the operation and then creating a new StringBuilder from the result.)
If you frequently modify the string, go with StringBuilder. Otherwise, if it's immutable anyway, go with String.
To answer your question on how to replace characters, check this out: http://download.oracle.com/javase/tutorial/java/data/buffers.html. StringBuilder operations is what you want.
Here's another good write-up on StringBuilder: http://www.yoda.arachsys.com/csharp/stringbuilder.html
If you need to lot of alter operations on your String, then you can go for StringBuilder. Go for StringBuffer if you are in multithreaded application.
Both a String and a StringBuilder use about the same amount of memory. Why do you think it is “much”?
If you have measured (for example with jmap -histo:live) that the classes [C and java.lang.String take up most of the memory in the heap, only then should you think further in this direction.
Maybe there are multiple strings with the same value. Then, since Strings are immutable, you could intern the duplicate strings. Don't use String.intern for it, since it has bad performance characteristics, but Google Guava's Interner.

Speed issue while appending strings

Whenever I try to add the numbers in string like:
String s=new String();
for(int j=0;j<=1000000;j++)
s+=String.valueOf(j);
My program is adding the numbers, but very slowly. But When I altered my program and made it like:
StringBuffer sb=new StringBuffer();
for(int j=0;j<=1000000;j++)
sb.append(String.valueOf(j));
I got the result very quickly. Why is that so?
s+=String.valueOf(j); needs to allocate a new String object every time it is called, and this is expensive. The StringBuffer only needs to grow some internal representation when the contained string is too large, which happens much less often.
It would probably be even faster if you used a StringBuilder, which is a non-synchronized version of a StringBuffer.
One thing to note is that while this does apply to loops and many other cases, it does not necessarily apply to all cases where Strings are concatenated using +:
String helloWorld = getGreeting() + ", " + getUsername() + "!";
Here, the compiler will probably optimize the code in a way that it sees fit, which may or may not be creating a StringBuilder, since that is also an expensive operation.
Because s += "string" creates a new instance. A String is immutable. StringBuffer or StringBuilder adds the String without creating a new instance.
In Java as in .NET Strings are immutable. They cannot be changed after creation. The result is that using the +operator will create a new string and copy the contents of both strings into it.
A StringBuffer will double the allocated space every time it runs out of space to add characters. Thus reducing the amount of memory allocations.
Take a look at this, from the Javaspecialists newsletter by Heinz Kabutz:
http://www.javaspecialists.eu/archive/Issue068.html
and this later article:
http://java.sun.com/developer/technicalArticles/Interviews/community/kabutz_qa.html

Strings are immutable - that means I should never use += and only StringBuffer?

Strings are immutable, meaning, once they have been created they cannot be changed.
So, does this mean that it would take more memory if you append things with += than if you created a StringBuffer and appended text to that?
If you use +=, you would create a new 'object' each time that has to be saved in the memory, wouldn't you?
Yes, you will create a new object each time with +=. That doesn't mean it's always the wrong thing to do, however. It depends whether you want that value as a string, or whether you're just going to use it to build the string up further.
If you actually want the result of x + y as a string, then you might as well just use string concatenation. However, if you're really going to (say) loop round and append another string, and another, etc - only needing the result as a string at the very end, then StringBuffer/StringBuilder are the way to go. Indeed, looping is really where StringBuilder pays off over string concatenation - the performance difference for 5 or even 10 direct concatenations is going to be quite small, but for thousands it becomes a lot worse - basically because you get O(N2) complexity with concatenation vs O(N) complexity with StringBuilder.
In Java 5 and above, you should basically use StringBuilder - it's unsynchronized, but that's almost always okay; it's very rare to want to share one between threads.
I have an article on all of this which you might find useful.
Rule of thumb is simple:
If you are running concatenations in a loop, don't use +=
If you are not running concatenations in a loop, using += simply does not matter. (Unless a performance critical application
In Java 5 or later, StringBuffer is thread safe, and so has some overhead that you shouldn't pay for unless you need it. StringBuilder has the same API but is not thread safe (i.e. you should only use it internal to a single thread).
Yes, if you are building up large strings, it is more efficient to use StringBuilder. It is probably not worth it to pass StringBuilder or StringBuffer around as part of your API. This is too confusing.
I agree with all the answers posted above, but it will help you a little bit to understand more about the way Java is implemented. The JVM uses StringBuffers internally to compile the String + operator (From the StringBuffer Javadoc):
String buffers are used by the
compiler to implement the binary
string concatenation operator +. For
example, the code:
x = "a" + 4 + "c"
is compiled to the equivalent of:
x = new StringBuffer().append("a").append(4).append("c")
.toString()
Likewise, x += "some new string" is equivalent to x = x + "some new string". Do you see where I'm going with this?
If you are doing a lot of String concatenations, using StringBuffer will increase your performance, but if you're only doing a couple of simple String concatenations, the Java compiler will probably optimize it for you, and you won't notice a difference in performance
Yes. String is immutable. For occasional use, += is OK. If the += operation is intensive, you should turn to StringBuilder.
But the garbage collector will end up freeing the old strings once there are no references to them
Exactly. You should use a StringBuilder though if thread-safety isn't an issue.
As a side note: There might be several String objects using the same backing char[] - for instance whenever you use substring(), no new char[] will be created which makes using it quite efficient.
Additionally, compilers may do some optimization for you. For instance if you do
static final String FOO = "foo";
static final String BAR = "bar";
String getFoobar() {
return FOO + BAR; // no string concatenation at runtime
}
I wouldn't be surprised if the compiler would use StringBuilder internally to optimize String concatenation where possible - if not already maybe in the future.
I think it relies on the GC to collect the memory with the abandoned string.
So doing += with string builder will be definitely faster if you have a lot of operation on string manipulation. But it's shouldn't a problem for most cases.
Yes you would and that is exactly why you should use StringBuffer to concatenate alot of Strings.
Also note that since Java 5 you should also prefer StringBuilder most of the time. It's just some sort of unsynchronized StringBuffer.
You're right that Strings are immutable, so if you're trying to conserve memory while doing a lot of string concatenation, you should use StringBuilder rather than +=.
However, you may not mind. Programs are written for their human readers, so you can go with clarity. If it's important that you optimize, you should profile first. Unless your program is very heavily weighted toward string activity, there will probably be other bottlenecks.
No
It will not use more memory. Yes, new objects are created, but the old ones are recycled. In the end, the amount of memory used is the same.

Categories

Resources