How to reuse a java.lang.StringBuilder

It’s common knowledge in Java that you want to clear a StringBuilder object, and not recreate it. Why? GC for instance. But, surprisingly enough, there is no clear() method on the StringBuilder class, and so we resort to manual clear methods. The ones I’ve seen are:

  • new StringBuilder which basically recreates the object
  • setLength(0) which changes the internal flags of the StringBuilder
  • delete(0,sb.length()) which deletes the whole buffer

One would think that the best technique is setLength – but I’ve decided to give it a short test.
Here is the code I’ve used:


package com.tona;

import java.util.Random;

public class TestStringBuffer {
private static final int NUM_OF_RUNS = 100000;
private static final int MAX_LENGTH = 1000;
private static Random rand = new Random();

private static int fillString(StringBuilder sb,boolean isSameLenString) {

int length;

if (isSameLenString)
length = MAX_LENGTH;
else
length = rand.nextInt(MAX_LENGTH);

for (int i = 0; i < length; ++i) sb.append("a"); return length; } private void runBenchmark(boolean isSameLenString) { StringBuilder sb = new StringBuilder(); long start = System.currentTimeMillis(); for (int i = 0; i < NUM_OF_RUNS; ++i) { fillString(sb,isSameLenString); sb.setLength(0); } long end = System.currentTimeMillis(); long diffWithLen0 = end - start; start = System.currentTimeMillis(); for (int i = 0; i < NUM_OF_RUNS; ++i) { fillString(sb,isSameLenString); sb = new StringBuilder(); } end = System.currentTimeMillis(); long diffWithNew = end - start; start = System.currentTimeMillis(); for (int i = 0; i < NUM_OF_RUNS; ++i) { fillString(sb,isSameLenString); sb = new StringBuilder(MAX_LENGTH); } end = System.currentTimeMillis(); long diffWithNewConstLength = end - start; start = System.currentTimeMillis(); for (int i = 0; i < NUM_OF_RUNS; ++i) { fillString(sb,isSameLenString); sb.delete(0, sb.length()); } end = System.currentTimeMillis(); long diffWithDelete = end - start; start = System.currentTimeMillis(); for (int i = 0; i < NUM_OF_RUNS; ++i) { int length = fillString(sb,isSameLenString); sb.delete(0, length); } end = System.currentTimeMillis(); long diffWithDeleteConstLength = end - start; System.out.println("With setLength(0) " + diffWithLen0); System.out.println("With new StringBuilder() " + diffWithNew); System.out.println("With new StringBuilder(MAX_LENGTH) " + diffWithNewConstLength); System.out.println("With delete(0, sb.length()) " + diffWithDelete); System.out.println("With delete(0, length) " + diffWithDeleteConstLength); } public static void main(String[] args) { TestStringBuffer test = new TestStringBuffer(); System.out.println("Constant length string"); test.runBenchmark(true); System.out.println("Changing length string"); test.runBenchmark(false); } } [/java]

And here are the results:

Constant length string
With setLength(0) 1524
With new StringBuilder() 1501
With new StringBuilder(MAX_LENGTH) 1365
With delete(0, sb.length()) 1369
With delete(0, length) 1391
Changing length string
With setLength(0) 686
With new StringBuilder() 743
With new StringBuilder(MAX_LENGTH) 796
With delete(0, sb.length()) 715
With delete(0, length) 698

(Note that changing string length uses a Random, so results may vary).
With StringBuilder object with a fixed length, the new StringBuilder with the predefined length is the best option, although not much slower than the delete method. With the varying length strings, setLength and delete and more of less on par (give it a few runs and you'll see it for yourself).
So, now you know how to clean your StringBuilder object. Enjoy.

One thought on “How to reuse a java.lang.StringBuilder

  1. Nice benchmark, but since the amount of added chars depends on a random value, it is possible that in one test more elements get added than in another test. Of course with 100k randomly drawn numbers this difference might be small. Never the less it leaves room for questions.

Leave a Reply

Your email address will not be published. Required fields are marked *