String concatenation via the “+” operator is one of the most convenient things to do in Java. It is also one of the most expensive, in terms of memory and performance.
When the compiler sees
String s = "abc" + someInt + someArray[index];
or any other concatenation, it **ACTUALLY** generates (for runtime use) the code sequence that follows (or, at least, the bytecode equivalent of it):
StringBuffer temp = new StringBuffer( ); temp.append( String.valueOf( "abc" ) ); temp.append( String.valueOf( someInt ) ); temp.append( String.valueOf( someArray[index] ); String s = temp.toString( );
The weak spot in all this is the construction of the StringBuffer object: the size of the buffer is ALWAYS 16 characters.
Then, as data is appended to the buffer, if more space is needed the size of the buffer is doubled and the old data is copied to the new buffer.
So to optimize we have to bypass the automatic StringBuffer when possible.
In ‘Replace/remove character in a String’, a snippet is given to replace a character at a specific position. An optimized version, using the StringBuffer would be:
public static String replaceCharAt(String s, int pos, char c) { StringBuffer buf = new StringBuffer( s ); buf.setCharAt( pos, c ); return buf.toString( ); }
Only one buffer created, exactly the right size. Converting a StringBuffer to a String costs almost nothing, as the actual buffer is shared between the two.
In the same article, a snippet about removing a character in a String can be optimized like:
public static String removeChar(String s, char c) { StringBuffer r = new StringBuffer( s.length() ); r.setLength( s.length() ); int current = 0; for (int i = 0; i < s.length(); i ++) { char cur = s.charAt(i); if (cur != c) r.setCharAt( current++, cur ); } return r.toString(); } In the original version, a new String object was created and discarded immediately!
The weak spot of the original method to remove a character is when the parameter s passed have than 17 characters, the temporary StringBuffer created by the compiler will have to be extended. To optimize, simply rewrite the method using a StringBuffer with the correct size:
public static String removeCharAt(String s, int pos) { StringBuffer buf = new StringBuffer( s.length() - 1 ); buf.append( s.substring(0,pos) ).append( s.substring(pos+1) ); return buf.toString(); }