I've implemented Roedy's idea using StringBuilders rather than char[]s
(which still have a fixed size), as it means i don't have to write all the
bookkeeping code myself. I doubt there's a significant performance impact.
Anyone who disagrees is free to write a different implementation!
Here is one implementation of a Fast Concatenate to replace
StringBuilder. It needs two speedups, I don't know are possible
without some sort of hack. It would be nice if String had a String...
constructor to avoid the creation of two buffers and an extra copy.
/*
* @(#)FastCat.java
*
* Summary: Stripped down, fast replacement for StringBuilder and
StringWriter to build concatentated Strings.
*
* Copyright: (c) 2009 Roedy Green, Canadian Mind Products,
http://mindprod.com
*
* Licence: This software may be copied and used freely for any
purpose but military.
*
http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.6+
*
* Created with: IntelliJ IDEA IDE.
*
* Version History:
* 1.0 2009-09-29 - initial release
*/
package com.mindprod.fastcat;
import java.io.File;
import java.util.ArrayList;
/**
* Stripped down, fast replacement for StringBuilder and StringWriter
to build concatentated Strings.
*
* @author Roedy Green, Canadian Mind Products
* 1.0 2009-09-29 - initial release
* @since 2009-09-29
*/
public class FastCat
{
// ------------------------------ FIELDS
------------------------------
/**
* private collection of pieces we will later glue together once
we know the size of the final String
*/
final ArrayList<String> pieces;
private int length = 0;
// -------------------------- PUBLIC INSTANCE METHODS
--------------------------
/**
* no-arg constructor
*/
public FastCat()
{
pieces = new ArrayList<String>( 20 );
}
/**
* constructor
*
* @param estNumberOfPieces estimated number of chunks you will
concatenate. It is better to estimate slightly high than slightly
low.
*/
public FastCat( int estNumberOfPieces )
{
pieces = new ArrayList<String>( estNumberOfPieces );
}
/**
* append String
*
* @param s String to append
*/
public void append( String s )
{
length += s.length();
pieces.add( s );
}
/**
* append arbitrary number of strings
*
* @param ss comma-separated list of Strings to append
*/
public void append( String... ss )
{
for ( String s : ss )
{
length += s.length();
pieces.add( s );
}
}
/**
* append Object
*
* @param o Object to append. toString is called to acquire a
String to concatenate.
*/
public void append( Object o )
{
final String s = o.toString();
length += s.length();
pieces.add( s );
}
/**
* append arbitrary number of Objects
*
* @param ,, comma-separated list of Objects to to append.
toString is called to acquire a String to concatenate.
*/
public void append( Object... oo )
{
for ( Object o : oo )
{
final String s = o.toString();
length += s.length();
pieces.add( s );
}
}
/**
* empty the concatenated String being created
*/
public void clear()
{
pieces.clear();
}
/**
* Get the concatenation of all the strings appended so far
*/
public String toString()
{
int offset = 0;
final char[] buffer = new char[length];
for ( String p : pieces )
{
for ( int i = 0; i < p.length(); i++ )
{
// copy over that once piece, char by char. Can this
be improved?
buffer[ offset++ ] = p.charAt( i );
}
}
return new String( buffer ); // Would like some way to just
hand buffer over to String to avoid copy.
}
// --------------------------- main() method
---------------------------
/**
* test harness
*
* @param args not used.
*/
public static void main( String[] args )
{
FastCat f = new FastCat( 7 );
f.append( "Hello" );
f.append( " " );
f.append( "World. " );
f.append( new File( "temp.txt" ) );
f.append( " " ,"abc", "def" );
System.out.println( f.toString() );
// prints Hello World. temp.txt abcdef
}
}
--
Roedy Green Canadian Mind Products
http://mindprod.com
On two occasions I have been asked [by members of Parliament], "Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?" I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
~ Charles Babbage (born: 1791-12-26 died: 1871-10-18 at age: 79)