Reputation:
I am confused between two codes, why the second one I am going to give here is more efficient than the first one.
Both of the codes just reverse a String, but first code is slower than the other and I am not able to understand why.
The first code is:
String reverse1(String s) {
String answer = "";
for(int j = s.length() - 1; j >= 0; j--) {
answer += s.charAt(j);
}
return answer;
}
The second code is:
String reverse2(String s) {
char answer[] = new char[s.length()];
for(int j = s.length() - 1; j >= 0; j--) {
answer[s.length() - j - 1] = s.charAt(j);
}
return new String(answer);
}
And I'm not able to understand how the second code is more efficient than the first one, I'd appreciate any insight on this.
Upvotes: 0
Views: 98
Reputation: 4662
The JVM treats strings as immutable. Hence, every time you append to the existing string, you are actually create a new string! This means that a new string object has to be created in heap for every loop iteration. Creating an object and maintaining its lifecycle has its overhead. Add to that the garbage collection of the discarded strings (the string created in the previous iteration won't have a reference to it in the next, and hence, it is collected by the JVM).
You should consider using a StringBuilder. I ran some tests and the time taken by the StringBuilder code is not much smaller than that of the fixed-length array.
There are some nuances to how the JVM treats strings. There are things like string interning that the JVM does so that it does not have to create a new object for multiple strings with the same content. You might want to look into that.
Upvotes: 0
Reputation: 4915
Why is the second code more efficient than the first one?
String is immuable, by answer += s.charAt(j);
you are creating a new instance of String in each loop, which makes your code slow.
Instead of String, you are suggested to use StringBuilder
in a single thread context, for both performance and readablity(might be a little slower than fix-sized char array but has a better readablity):
String reverse1(String s) {
StringBuilder answer = new StringBuilder("");
for (int j = s.length() - 1; j >= 0; j--)
answer.append(s.charAt(j));
return answer.toString();
}
Upvotes: 0
Reputation: 510
In this code you are creating a new String object in each loop iteration,because String is immutable class
String reverse1(String s) {
String answer = "";
for (int j = s.length() - 1; j >= 0; j--)
answer += s.charAt(j);
return answer;
}
In this code you have already allocated memory to char array,Your code will create only single String at last line, so it is more efficient
String reverse2(String s) {
char answer[] = new char[s.length()];
for (int j = s.length() - 1; j >= 0; j--)
answer[s.length() - j - 1] = s.charAt(j);
return new String(answer);
}
Upvotes: 0
Reputation: 667
String
object is immutable and every time you made an add operation you create another object, allocating space and so on, so it's quite inefficient when you need to concatenate many strings.
Your char array method fits your specific need well, but if you need more generic string concatenation support, you could consider StringBuilder
Upvotes: 0
Reputation: 522712
Your question is perhaps difficult to answer exactly, in part because the answer would depend on the actual implementation of the first version. This, in turn, would depend on what version of Java you are using, and what the compiler decided to do.
Assuming that the compiler keeps the first version verbatim as you wrote it, then yes, the first version might be more inefficient, because it would require allocating a new string for each step in the reversal process. The second version, on the contrary, just maintains a single array of characters.
However, if the compiler is smart enough to use a StringBuilder
, then the answer changes. Consider the following first version:
String reverse1(String s) {
StringBuilder answer = new StringBuilder();
for (int j = s.length() - 1; j >= 0; j--)
answer.append(s.charAt(j));
return answer;
}
Under the hood, StringBuilder
is implemented using a character array. So calling StringBuilder#append
is somewhat similar to the second version, i.e. it just adds new characters to the end of the buffer.
So, if your first version executes using literal String
, then it is more inefficient than the second version, but using StringBuilder
it might be on par with the second version.
Upvotes: 1
Reputation: 114528
The first code declares
String answer;
Strings are immutable. Therefore, every append operation reallocates the entire string, copies it, then copies in the new character.
The second code declares
char answer[];
Arrays are mutable, so each iteration copies only a single character. The final string is created once, not once per iteration of the loop.
Upvotes: 3
Reputation: 1654
String is immutable. Whenever you do answer += s.charAt(j);
it creates a new object. Try printing GC logs using -XX:+PrintGCDetails
and see if the latency is caused by minor GC.
Upvotes: 0