package co.spillikin.java.jkia; import java.util.ArrayList; /** * Java Know It All: String concatenation. * * Know it all #1: You must concatenate StringBuffer, not String in order to * achieve best performance. Convert to String when finished. * Know it all #2: No you don't. The JIT optimizes concatenation for you. * * Let's find out!! * * @author chris * */ public class StringKIA { // Number of times to rerun each concatenation private static long AWHOLELOTOFTIMES = 512; // Length of each String / StringBuffer private static long SIZE = 256; // Useless work so JIT doesn't say "Hey, String isn't used for anything!" private ArrayList useless = new ArrayList(); public static void main(String[] args) { StringKIA me = new StringKIA(); System.out.println("All strings are " + SIZE + " in length and " + "assembled one character at a time."); System.out.println("Concatenating " + AWHOLELOTOFTIMES + " Strings..." ); long k2Time = me.kiaTwo(); System.out.println("Concatenating " + AWHOLELOTOFTIMES + " buffers and turning " + "each into a String..."); long k1Time = me.kiaOne(); System.out.println("StringBuffer concat took " + k1Time + "ms"); System.out.println("String concat took " + k2Time + "ms"); if ( k1Time < k2Time ) { System.out.println ("Know it all #1 was correct."); System.out.println ("Build using a buffer first, then convert to a String."); } else { System.out.println ("Know it all #2 was correct."); System.out.println ("It is ok to simply concat a String. No buf needed."); } } /** * Concatenate a modestly long StringBuffer and convert to a String * a whole bunch of times. * @return The number of millis it took. */ private long kiaOne () { long elapsedTime = System.currentTimeMillis(); StringBuffer longBuf = new StringBuffer(); for ( long j = 0; j < AWHOLELOTOFTIMES; j++ ) { for ( long i = 0; i < SIZE; i++ ) { longBuf.append("a"); } String aString = longBuf.toString(); work(aString); } return elapsedTime = System.currentTimeMillis() - elapsedTime; } /** * Simple concatenate to a String a whole bunch of times. * @return The number of millis it took. */ private long kiaTwo () { long elapsedTime = System.currentTimeMillis(); String longStr = new String(); for ( long j = 0; j < AWHOLELOTOFTIMES; j++ ) { for ( long i = 0; i < SIZE; i++ ) { longStr = longStr + "a"; } work(longStr); } return elapsedTime = System.currentTimeMillis() - elapsedTime; } /** * In order to prevent the JIT from optimizing away our unused String, * let's use it for something stupid. */ private void work (String s) { // System.out.println("ss" + s); useless.add(s); useless.clear(); } }