Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is more efficient StringBuffer new() or delete(0, sb.length())?

It is often argued that avoiding creating objects (especially in loops) is considered good practice.

Then, what is most efficient regarding StringBuffer?

StringBuffer sb = new StringBuffer();
ObjectInputStream ois = ...;

for (int i=0;i<1000;i++) {

    for (j=0;i<10;j++) {
        sb.append(ois.readUTF());
    }
    ...

    // Which option is the most efficient? 
    sb = new StringBuffer(); // new StringBuffer instance?
    sb.delete(0,sb.length()); // or deleting content?

}

I mean, one could argue that creating an object is faster then looping through an array.

like image 444
Jérôme Verstrynge Avatar asked Aug 23 '11 23:08

Jérôme Verstrynge


2 Answers

First StringBuffer is thread-safe which will have bad performance compared to StringBuilder. StringBuilder is not thread safe but as a result is faster. Finally, I prefer just setting the length to 0 using setLength.

sb.setLength(0)

This is similar to .delete(...) except you don't really care about the length. Also probably a little faster since it doesn't need to 'delete' anything. Creating a new StringBuilder (or StringBuffer) would be less efficient. Any time you see new Java is creating a new object and placing that on the heap.

Note: After looking at the implementation of .delete and .setLength, .delete sets length = 0, and .setLength sets every thing to '\0' So you may get a little win with .delete

like image 93
Amir Raminfar Avatar answered Nov 18 '22 01:11

Amir Raminfar


Just to amplify the previous comments:

From looking at source, delete() always calls System.arraycopy(), but if the arguments are (0,count), it will call arraycopy() with a length of zero, which will presumably have no effect. IMHO, this should be optimized out since I bet it's the most common case, but no matter.

With setLength(), on the other hand, the call will increase the StringBuilder's capacity if necessary via a call to ensureCapacityInternal() (another very common case that should have been optimized out IMHO) and then truncates the length as delete() would have done.

Ultimately, both methods just wind up setting count to zero.

Neither call does any iterating in this case. Both make an unnecessary function call. However ensureCapacityInternal() is a very simple private method, which invites the compiler to optimize it nearly out of existence so it's likely that setLength() is slightly more efficient.

I'm extremely skeptical that creating a new instance of StringBuilder could ever be as efficient as simply setting count to zero, but I suppose that the compiler might recognize the pattern involved and convert the repeated instantiations into repeated calls to setLength(0). But at the very best, it would be a wash. And you're depending on the compiler to recognize the case.

Executive summary: setLength(0) is the most efficient. For maximum efficiency, pre-allocate the buffer space in StringBuilder when you create it.

like image 3
Edward Falk Avatar answered Nov 18 '22 01:11

Edward Falk