Hi.<div><br></div><div>As you know, java.lang.StringXXXX classes favor insertion to the end in terms of performance. Adding to beginning or middle of these sequences causes most of the array to be shifted toward the end every time. Every ones in a while I end up changing my algorithms those are based on prefixing strings (ex. building a fully qualified name from class name to root direction). Sometimes these kind of changes could result in less readable code. And I should note that, there are lots of developers out there who does not know the internal details of these classes. </div>
<div><br></div><div>Anyway, this behavior was frustrating me for a while and I decided to suggest a gap buffer based modification to AbstractStringBuilder to solve this problem but never had time before to prototype it.</div>
<div><br></div><div>I tested the original StringBuilder against the prototype. Preliminary results for the duration of 100000 insertions of a short string: </div><div><br></div><div><font class="Apple-style-span" face="'courier new', monospace"> Original | Prototype </font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> append => ~33 | ~34</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> insert beginning => ~32000 | ~38</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> insert random => ~16000 | ~10000</font></div><div><font class="Apple-style-span" face="arial, helvetica, sans-serif"><br></font></div>
<div><font class="Apple-style-span" face="arial, helvetica, sans-serif"><br></font></div><div><font class="Apple-style-span" face="arial, helvetica, sans-serif">A negligible overhead appears for appending (which could be avoided with shortcuts), but lots of performance gain achieved for other cases. </font></div>
<div><font class="Apple-style-span" face="arial, helvetica, sans-serif">If we handle insertion at zero as a special case in insert method or if we add an another method like 'prepend', the insertion at beginning will show exactly same performance characteristics of insertion at the end. </font></div>
<div><font class="Apple-style-span" face="arial, helvetica, sans-serif"><br></font></div><div><font class="Apple-style-span" face="arial, helvetica, sans-serif">In my opinion, this is a well-worth modification to string building classes. If anybody agrees on sponsoring, I can tidy up code and contribute to OpenJDK.</font></div>
<div><font class="Apple-style-span" face="arial, helvetica, sans-serif"><br></font></div><div><span class="Apple-style-span" style="font-family: arial, helvetica, sans-serif; ">- Goktug</span></div><div><font class="Apple-style-span" face="arial, helvetica, sans-serif"> </font></div>
<div><font class="Apple-style-span" face="arial, helvetica, sans-serif"><br></font></div><div><font class="Apple-style-span" face="arial, helvetica, sans-serif">PS: I've used following code for rough testing:</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace"><div>
<div>private static final int LOOP_COUNT = 100000;</div><div><br></div><div>public static void main(String[] args) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>long nanoTime = System.nanoTime();</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>testStandardAppend();</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>//testAppendBeginning();</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>//testAppendRandom();</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>long span = System.nanoTime() - nanoTime;</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>System.out.println(span / 1000000);</div><div>
}</div><div><br></div><div>private static void testStandardAppend() {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>StringBuilder builder = new StringBuilder("initial");</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>for (int i = 0; i < LOOP_COUNT; i++) {</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>builder.append("tryouts");</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div>}</div><div><br></div><div>private static void testAppendBeginning() {</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>StringBuilder builder = new StringBuilder("initial");</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>for (int i = 0; i < LOOP_COUNT; i++) {</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>builder.insert(0, "tryouts");</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div>}</div><div><br></div><div>private static void testAppendRandom() {</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>Random random = new Random();</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>StringBuilder builder = new StringBuilder("initial");</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>for (int i = 0; i < LOOP_COUNT; i++) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>builder.insert(random.nextInt(builder.length()), "tryouts");</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>}</div><div>}</div></div></font></div>