FileDocCategorySizeDatePackage
AppenderHelper.javaAPI DocExample57841Wed Dec 06 11:58:28 GMT 2000tuning.stringconvert

AppenderHelper

public class AppenderHelper extends Object
The AppenderHelper class works around several inefficencies in the Java distribution.

The following items really need to be added to Java to eliminate the use of AppenderHelper:

  • Object needs the method appendTo(StringBuffer,int)
  • The classes in the Java distribution need to improve their conversions to Strings
(As an aside, there should really be an Appender interface, which StringBuffer implements with all the append methods defined.)

Instead, AppenderHelper supports the efficient appending of object's string representation to a StringBuffer. Basically this means that all the basic data types have their own conversion algorithms in this class which are considerably more efficient than the Java ones (except char which, of course, doesn't need conversion) and, in addition, several classes also have specialized conversion algorithms.

In addition, the whole thing is fully extensible (though I would prefer that it were made redundant by correct implementations in Java).

As an example

StringBuffer s = new StringBuffer();
s.append(567);
maps to
StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
a.append(s,567);
The difference is that in the first StringBuffer append, the StringBuffer append first asks Integer to convert the int 567 into a String. This conversion is not very efficient, and apart from being not as fast as it could be, also creates another temporary StringBuffer during the conversion (which in turn creates another internal char array). So for appending one int to the StringBuffer we get three temporary objects, the space they use, and a not particularly optimized conversion algorithm.

On the other hand, in the second AppenderHelper example, we create no extra objects at all, and use an optimized conversion algorithm. Which means that even though we have to call the StringBuffer append(char) lots of times, it is still faster and uses less resources from the VM (and yes, the two are related, one reason it is faster is because it uses less VM resources).

The easisest way to add support for using AppenderHelper with classes you have control over is to implement the Appendable interface.

For classes you do not control, you need to implement an AppendConverter class, and register it with the AppenderHelper.

But NOTE that if you do not need efficient conversion of objects (because you do not do much StringBuffer appending, or it happens in a part of the application that has plenty of spare time and resources), then there is no need to change the way you do things at the moment.

AppenderHelper can be used in a very similar way to StringBuffer, e.g.

StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
a.append(s,567).append(s," is ").append(s,33.5).append(s,'%');
and there is also a StringBufferWrapper class if you are feeling really lazy.

All data type conversions are specifically optimized by AppenderHelper. In addition, the classes specifically optimized by AppenderHelper (and so which do not need AppendConverter classes for them) are: all the classes coresponding to the basic datatypes (e.g. Integer, etc.); Object; java.util.Vector.

Note however that subclasses of these types are not specially optimized unless the correct overloaded append method is called, i.e. if java.util.Stack were not registered (which it is) then

StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
java.util.Stack stack = new java.util.Stack();
a.append(s,stack);
would be optimized because that calls the AppenderHelper.append(StringBuffer,java.util.Vector) method, but
StringBuffer s = new StringBuffer();
AppenderHelper a = AppenderHelper.SINGLETON;
java.util.Stack stack = new java.util.Stack();
a.append(s,(Object) stack);
would not be optimized because that calls the AppenderHelper.append(StringBuffer,Object) method, which requires the passed object's class to be registered for the correct AppendConverter to be used.

AppenderHelper is an application (i.e. has a runnable main method) which can be run to see examples of the improvements it brings.

see
main()
see
Appendable
see
AppendConverter
see
StringBufferWrapper
see
StringBuffer

Fields Summary
public static AppenderHelper
SINGLETON
public static int
DEFAULT_DEPTH
public static final char[]
TRUE
char array holding the characters for the string "true".
public static final char[]
FALSE
char array holding the characters for the string "false".
public static final char[]
NULL
char array holding the characters for the string "null".
public static final char[]
NEGATIVE_INFINITY
char array holding the characters for the string "-Infinity".
public static final char[]
POSITIVE_INFINITY
char array holding the characters for the string "Infinity".
public static final char[]
NaN
char array holding the characters for the string "NaN".
public static final char[]
DOUBLE_ZERO
char array holding the characters for the string "0.0".
public static final char[]
DOUBLE_ZERO2
char array holding the characters for the string "0.00".
public static final char[]
DOUBLE_ZERO0
char array holding the characters for the string "0.".
public static final char[]
DOT_ZERO
char array holding the characters for the string ".0".
public static final char[]
COMMA_SPACE
char array holding the characters for the string ", ".
private static final long
doubleSignMask
private static final long
doubleExpMask
private static final long
doubleFractMask
private static final int
doubleExpShift
private static final int
doubleExpBias
private static final int
floatSignMask
private static final int
floatExpMask
private static final int
floatFractMask
private static final int
floatExpShift
private static final int
floatExpBias
private static final Hashtable
append_map
private static final Hashtable
clsname_cache
private static final char[]
charForDigit
private static final float[]
f_magnitudes
private static final double[]
d_magnitudes
public static final char[]
ZEROS
Constructors Summary
protected AppenderHelper()
AppenderHelper is a singleton, so the constructor is just narrowed in scope to disallow external classes to create further instances.

Subclasses can create new instances (required in order to allow them to create instances of themselves), but should refrain from doing so.



                                            
 

Methods Summary
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Appendable o)
Appends the string representation of the Appendable argument to the string buffer. Does so by calling the appendTo method of the Appendable.

param
s the StringBuffer to append the object to.
param
o the Appendable to be appended.
return
this AppenderHelper
see
Appendable

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	o.appendTo(s, DEFAULT_DEPTH);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Appendable o, int depth)
Appends the string representation of the Appendable argument to the string buffer. Does so by calling the appendTo method of the Appendable.

param
s the StringBuffer to append the object to.
param
o the Appendable to be appended.
param
depth the depth with which to display the Appendable.
return
this AppenderHelper
see
Appendable

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	if (depth <= 0)
		appendDepth0To(s,o);
	else
		o.appendTo(s, depth);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Boolean o)
Appends the string representation of the Boolean argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Boolean to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.booleanValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Byte o)
Appends the string representation of the Byte argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Byte to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.byteValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Character o)
Appends the string representation of the Character argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Character to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.charValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Double o)
Appends the string representation of the Double argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Double to be appended.
return
this AppenderHelper

	return append(s,o.doubleValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Float o)
Appends the string representation of the Float argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Float to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.floatValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Integer o)
Appends the string representation of the Integer argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Integer to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.intValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Long o)
Appends the string representation of the Long argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Long to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.longValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Object o)
Appends the string representation of the Object argument to the string buffer. If o is an Appendable, this will delegate the append to the appendTo method. If o has a registered append mapping, then this will delegate the append to the registered AppendConverter object.

param
s the StringBuffer to append the object to.
param
o the Object to be appended.
return
this AppenderHelper
see
Appendable
see
AppendConverter

	return append(s, o, DEFAULT_DEPTH);
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, char[] c)
Appends the string representation of the char array argument to the string buffer.

param
s the StringBuffer to append the object to.
param
c the characters to be appended.
param
offset the index of the first character to append.
param
len the number of characters to append.
return
this AppenderHelper
see
StringBuffer#append(char[])

	if (c == null)
	{
		s.append(NULL);
		return this;
	}
	s.append(c);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Object o, int depth)
Appends the string representation of the Object argument to the string buffer. If o is an Appendable, this will delegate the append to the appendTo method. If o has a registered append mapping, then this will delegate the append to the registered AppendConverter object.

param
s the StringBuffer to append the object to.
param
o the Object to be appended.
param
depth the depth with which to display the object.
return
this AppenderHelper
see
Appendable
see
AppendConverter

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	if (depth <= 0)
		appendDepth0To(s,o);
	else if (o instanceof Appendable)
		((Appendable) o).appendTo(s, depth);
	else
	{
		AppendConverter h = (AppendConverter) append_map.get(o.getClass());
		if (h == null)
			s.append(o);
		else
			h.appendObj(this, s, o, depth);
	}
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.Short o)
Appends the string representation of the Short argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the Short to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	return append(s,o.shortValue());
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.lang.String o)
Appends the string representation of the String argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the String to be appended.
return
this AppenderHelper

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	s.append(o);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.util.Vector o)
Appends a java.util.Vector to a StringBuffer.

Since Vector is an object containing other objects, the contained objects are also appended to the StringBuffer. These appended objects are also asked to be appended by the AppenderHelper object.

param
s the StringBuffer to append the object to.
param
o the Vector who's display is to be appended.

	append(s, o, DEFAULT_DEPTH);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, java.util.Vector o, int depth)
Appends a java.util.Vector to a StringBuffer.

Since Vector is an object containing other objects, the contained objects are also appended to the StringBuffer. These appended objects are also asked to be appended by the AppenderHelper object.

The depth parameter specifies how deep the contained objects network should be asked to appended to the StringBuffer. A depth of 0 means just use a default representation of the object with no further contained objects asked to rpresent themselves.

param
s the StringBuffer to append the object to.
param
o the Vector who's display is to be appended.
param
depth depth of display for the Vector.

	if (o == null)
	{
		s.append(NULL);
		return this;
	}
	if (depth <= 0)
	{
		appendDepth0To(s,o);
	}
	else
	{
		depth--;
		int size = o.size();
		s.append('[");
		if (size != 0)
		{
			this.append(s, o.elementAt(0), depth);
			for (int i = 1; i < size; i++)
			{
				s.append(COMMA_SPACE);
				this.append(s, o.elementAt(i), depth);
			}
		}
		s.append(']");
	}
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, boolean b)
Appends the string representation of the boolean argument to the string buffer.

param
s the StringBuffer to append the object to.
param
o the boolean to be appended.
return
this AppenderHelper

	if (b)
		s.append(TRUE);
	else
		s.append(FALSE);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, char[] c, int offset, int len)
Appends the string representation of a subarray of the char array argument to the string buffer.

param
s the StringBuffer to append the object to.
param
c the characters to be appended.
param
offset the index of the first character to append.
param
len the number of characters to append.
return
this AppenderHelper
see
StringBuffer#append(char[], int, int)

	if (c == null)
	{
		s.append(NULL);
		return this;
	}
	s.append(c,offset,len);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, char c)
Appends the character to the string buffer.

param
s the StringBuffer to append the object to.
param
c the character to be appended.
return
this AppenderHelper
see
StringBuffer#append(char)

	s.append(c);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, double d)
Appends the string representation of the double argument to the string buffer.

param
s the StringBuffer to append the object to.
param
d the double to be appended.
return
this AppenderHelper
see
StringBuffer#append(double)

	if (d == Double.NEGATIVE_INFINITY)
		s.append(NEGATIVE_INFINITY);
	else if (d == Double.POSITIVE_INFINITY)
		s.append(POSITIVE_INFINITY);
	else if (d != d)
		s.append(NaN);
	else if (d == 0.0)
	{
		if ( (Double.doubleToLongBits(d) & doubleSignMask) != 0)
			s.append('-");
		s.append(DOUBLE_ZERO);
	}
	else
	{
		if (d < 0)
		{
			s.append('-");
			d = -d;
		}
		if (d >= 0.001 && d < 0.01)
		{
			long i = (long) (d * 1E20);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			s.append(DOUBLE_ZERO2);
			appendFractDigits(s, i,-1);
		}
		else if (d >= 0.01 && d < 0.1)
		{
			long i = (long) (d * 1E19);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			s.append(DOUBLE_ZERO);
			appendFractDigits(s, i,-1);
		}
		else if (d >= 0.1 && d < 1)
		{
			long i = (long) (d * 1E18);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			s.append(DOUBLE_ZERO0);
			appendFractDigits(s, i,-1);
		}
		else if (d >= 1 && d < 10)
		{
			long i = (long) (d * 1E17);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,1);
		}
		else if (d >= 10 && d < 100)
		{
			long i = (long) (d * 1E16);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,2);
		}
		else if (d >= 100 && d < 1000)
		{
			long i = (long) (d * 1E15);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,3);
		}
		else if (d >= 1000 && d < 10000)
		{
			long i = (long) (d * 1E14);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,4);
		}
		else if (d >= 10000 && d < 100000)
		{
			long i = (long) (d * 1E13);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,5);
		}
		else if (d >= 100000 && d < 1000000)
		{
			long i = (long) (d * 1E12);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,6);
		}
		else if (d >= 1000000 && d < 10000000)
		{
			long i = (long) (d * 1E11);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,7);
		}
		else
		{
			int magnitude = magnitude(d);
			long i;
			if (magnitude < -305)
				i = (long) (d*1E18 / d_magnitudes[magnitude + 324]);
			else
				i = (long) (d / d_magnitudes[magnitude + 323 - 17]);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i, 1);
			s.append('E");
			append(s,magnitude);
		}
	}
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, float d)
Appends the string representation of the float argument to the string buffer.

param
s the StringBuffer to append the object to.
param
d the float to be appended.
return
this AppenderHelper
see
StringBuffer#append(float)

	if (d == Float.NEGATIVE_INFINITY)
		s.append(NEGATIVE_INFINITY);
	else if (d == Float.POSITIVE_INFINITY)
		s.append(POSITIVE_INFINITY);
	else if (d != d)
		s.append(NaN);
	else if (d == 0.0)
	{
		if ( (Float.floatToIntBits(d) & floatSignMask) != 0)
			s.append('-");
		s.append(DOUBLE_ZERO);
	}
	else
	{
		if (d < 0)
		{
			s.append('-");
			d = -d;
		}
		if (d >= 0.001F && d < 0.01F)
		{
			long i = (long) (d * 1E12F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			s.append(DOUBLE_ZERO2);
			appendFractDigits(s, i,-1);
		}
		else if (d >= 0.01F && d < 0.1F)
		{
			long i = (long) (d * 1E11F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			s.append(DOUBLE_ZERO);
			appendFractDigits(s, i,-1);
		}
		else if (d >= 0.1F && d < 1F)
		{
			long i = (long) (d * 1E10F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			s.append(DOUBLE_ZERO0);
			appendFractDigits(s, i,-1);
		}
		else if (d >= 1F && d < 10F)
		{
			long i = (long) (d * 1E9F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,1);
		}
		else if (d >= 10F && d < 100F)
		{
			long i = (long) (d * 1E8F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,2);
		}
		else if (d >= 100F && d < 1000F)
		{
			long i = (long) (d * 1E7F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,3);
		}
		else if (d >= 1000F && d < 10000F)
		{
			long i = (long) (d * 1E6F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,4);
		}
		else if (d >= 10000F && d < 100000F)
		{
			long i = (long) (d * 1E5F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,5);
		}
		else if (d >= 100000F && d < 1000000F)
		{
			long i = (long) (d * 1E4F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,6);
		}
		else if (d >= 1000000F && d < 10000000F)
		{
			long i = (long) (d * 1E3F);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i,7);
		}
		else
		{
			int magnitude = magnitude(d);
			long i;
			if (magnitude < -35)
				i = (long) (d*1E10F / f_magnitudes[magnitude + 45]);
			else
				i = (long) (d / f_magnitudes[magnitude + 44 - 9]);
			i = i%100 >= 50 ? (i/100) + 1 : i/100;
			appendFractDigits(s, i, 1);
			s.append('E");
			append(s,magnitude);
		}
	}
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, long i)
Appends the string representation of the long argument to the string buffer.

param
s the StringBuffer to append the object to.
param
i the long to be appended.
return
this AppenderHelper
see
StringBuffer#append(long)

	if (i < 0)
	{
		if (i == Long.MIN_VALUE)
		{
			//cannot make this positive due to integer overflow
			s.append("-9223372036854775808");
			return this;
		}
		s.append('-");
		i = -i;
	}
	long mag = magnitude(i);
	long c;
	while ( mag > 1 )
	{
		c = i/mag;
		s.append(charForDigit[(int) c]);
		c *= mag;
		if ( c <= i)
			i -= c;
		mag /= 10;
	}
	s.append(charForDigit[(int) i]);
	return this;
public tuning.stringconvert.AppenderHelperappend(java.lang.StringBuffer s, int i)

	if (i < 0)
	{
		if (i == Integer.MIN_VALUE)
		{
			//cannot make this positive due to integer overflow
			s.append("-2147483648");
			return this;
		}
		s.append('-");
		i = -i;
	}
	int mag;
	int c;
	if (i < 10)
	{
		//one digit
		s.append(charForDigit[i]);
		return this;
	}
	else if (i < 100)
	{
		//two digits
		s.append(charForDigit[i/10]);
		s.append(charForDigit[i%10]);
		return this;
	}
	else if (i < 1000)
	{
		//three digits
		s.append(charForDigit[i/100]);
		s.append(charForDigit[(c=i%100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else if (i < 10000)
	{
		//four digits
		s.append(charForDigit[i/1000]);
		s.append(charForDigit[(c=i%1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else if (i < 100000)
	{
		//five digits
		s.append(charForDigit[i/10000]);
		s.append(charForDigit[(c=i%10000)/1000]);
		s.append(charForDigit[(c%=1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else if (i < 1000000)
	{
		//six digits
		s.append(charForDigit[i/100000]);
		s.append(charForDigit[(c=i%100000)/10000]);
		s.append(charForDigit[(c%=10000)/1000]);
		s.append(charForDigit[(c%=1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else if (i < 10000000)
	{
		//seven digits
		s.append(charForDigit[i/1000000]);
		s.append(charForDigit[(c=i%1000000)/100000]);
		s.append(charForDigit[(c%=100000)/10000]);
		s.append(charForDigit[(c%=10000)/1000]);
		s.append(charForDigit[(c%=1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else if (i < 100000000)
	{
		//eight digits
		s.append(charForDigit[i/10000000]);
		s.append(charForDigit[(c=i%10000000)/1000000]);
		s.append(charForDigit[(c%=1000000)/100000]);
		s.append(charForDigit[(c%=100000)/10000]);
		s.append(charForDigit[(c%=10000)/1000]);
		s.append(charForDigit[(c%=1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else if (i < 1000000000)
	{
		//nine digits
		s.append(charForDigit[i/100000000]);
		s.append(charForDigit[(c=i%100000000)/10000000]);
		s.append(charForDigit[(c%=10000000)/1000000]);
		s.append(charForDigit[(c%=1000000)/100000]);
		s.append(charForDigit[(c%=100000)/10000]);
		s.append(charForDigit[(c%=10000)/1000]);
		s.append(charForDigit[(c%=1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
	else
	{
		//ten digits
		s.append(charForDigit[i/1000000000]);
		s.append(charForDigit[(c=i%1000000000)/100000000]);
		s.append(charForDigit[(c%=100000000)/10000000]);
		s.append(charForDigit[(c%=10000000)/1000000]);
		s.append(charForDigit[(c%=1000000)/100000]);
		s.append(charForDigit[(c%=100000)/10000]);
		s.append(charForDigit[(c%=10000)/1000]);
		s.append(charForDigit[(c%=1000)/100]);
		s.append(charForDigit[(c%=100)/10]);
		s.append(charForDigit[c%10]);
		return this;
	}
private static voidappendAsUnsignedHexadecimal(java.lang.StringBuffer s, int iin)

	long i = iin;
	if (i < 0)
		i += 4294967296L;

	long mag = magnitude16(i);
	long c;
	while ( mag > 1 )
	{
		c = i/mag;
		s.append(charForDigit[(int) c]);
		c *= mag;
		if ( c <= i)
			i -= c;
		mag = mag/16;
	}
	s.append(charForDigit[(int) i]);
public static final voidappendDepth0To(java.lang.StringBuffer s, java.lang.Object o)
Appends the default string representation of the object as given in Object.toString(). (The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.)

Of course, this is quicker and more efficient than that method, and does not create any extra extraneous objects.

param
s the StringBuffer to append the object representation to.
param
o the object who's default string representation is to appended.

	if (o == null)
	{
		s.append(NULL);
		return;
	}
	Class cls = o.getClass();
	String nme = (String) clsname_cache.get(cls);
	if (nme == null)
	{
		nme = cls.getName();
		clsname_cache.put(cls,nme);
	}
	s.append(nme).append('@");
	appendAsUnsignedHexadecimal(s,o.hashCode());
private static voidappendFractDigits(java.lang.StringBuffer s, long i, int decimalOffset)

        

	long mag = magnitude(i);
	long c;
	while ( i > 0 )
	{
		c = i/mag;
		s.append(charForDigit[(int) c]);
		decimalOffset--;
		if (decimalOffset == 0)
			s.append('.");
		c *= mag;
		if ( c <= i)
			i -= c;
		mag = mag/10;
	}
	if (i != 0)
		s.append(charForDigit[(int) i]);
	else if (decimalOffset > 0)
	{
		s.append(ZEROS[decimalOffset]);
		decimalOffset = 1;
	}

	decimalOffset--;
	if (decimalOffset == 0)
		s.append(DOT_ZERO);
	else if (decimalOffset == -1)
		s.append('0");
private static voidinitializeMaps()
Initializes the maps in the DisplayHelper with the InternalDisplayHelper's known classes.

	try
	{
		putInAppendMap(new BooleanAppender(),"java.lang.Boolean");
		putInAppendMap(new ByteAppender(),"java.lang.Byte");
		putInAppendMap(new CharacterAppender(),"java.lang.Character");
		putInAppendMap(new DoubleAppender(),"java.lang.Double");
		putInAppendMap(new FloatAppender(),"java.lang.Float");
		putInAppendMap(new IntegerAppender(),"java.lang.Integer");
		putInAppendMap(new LongAppender(),"java.lang.Long");
		putInAppendMap(new ShortAppender(),"java.lang.Short");
		putInAppendMap(new StringAppender(),"java.lang.String");
		putInAppendMap(new VectorAppender(),"java.util.Vector");
		putInAppendMap(new VectorAppender(),"java.util.Stack");
		char[] c = new char[0];
		putInAppendMap(new CharArrayAppender(),c.getClass());
		putInAppendMap(new ObjectAppender(),"java.lang.Object");
	}
	catch(ClassNotFoundException e){}
private static intmagnitude(double d)

	return magnitude(d,Double.doubleToLongBits(d));
private static intmagnitude(double d, long doubleToLongBits)

	int magnitude = 
		(int) ((((doubleToLongBits & doubleExpMask) >> doubleExpShift) - doubleExpBias) * 0.301029995663981);

	if (magnitude < -323)
		magnitude = -323;
	else if (magnitude > 308)
		magnitude = 308;

	if (d >= d_magnitudes[magnitude+323])
	{
		while(magnitude < 309 && d >= d_magnitudes[magnitude+323])
			magnitude++;
		magnitude--;
		return magnitude;
	}
	else
	{
		while(magnitude > -324 && d < d_magnitudes[magnitude+323])
			magnitude--;
		return magnitude;
	}
private static intmagnitude(float d)

	return magnitude(d,Float.floatToIntBits(d));
private static intmagnitude(float d, int floatToIntBits)

	int magnitude = 
		(int) ((((floatToIntBits & floatExpMask) >> floatExpShift) - floatExpBias) * 0.301029995663981);

	if (magnitude < -44)
		magnitude = -44;
	else if (magnitude > 38)
		magnitude = 38;

	if (d >= f_magnitudes[magnitude+44])
	{
		while(magnitude < 39 && d >= f_magnitudes[magnitude+44])
			magnitude++;
		magnitude--;
		return magnitude;
	}
	else
	{
		while(magnitude > -45 && d < f_magnitudes[magnitude+44])
			magnitude--;
		return magnitude;
	}
private static longmagnitude(long i)
Assumes i is positive. Returns the magnitude of i in base 10.

	if (i < 10L) return 1;
	else if (i < 100L) return 10L;
	else if (i < 1000L) return 100L;
	else if (i < 10000L) return 1000L;
	else if (i < 100000L) return 10000L;
	else if (i < 1000000L) return 100000L;
	else if (i < 10000000L) return 1000000L;
	else if (i < 100000000L) return 10000000L;
	else if (i < 1000000000L) return 100000000L;
	else if (i < 10000000000L) return 1000000000L;
	else if (i < 100000000000L) return 10000000000L;
	else if (i < 1000000000000L) return 100000000000L;
	else if (i < 10000000000000L) return 1000000000000L;
	else if (i < 100000000000000L) return 10000000000000L;
	else if (i < 1000000000000000L) return 100000000000000L;
	else if (i < 10000000000000000L) return 1000000000000000L;
	else if (i < 100000000000000000L) return 10000000000000000L;
	else if (i < 1000000000000000000L) return 100000000000000000L;
	else return  1000000000000000000L;
private static longmagnitude16(long i)
Assumes i is positive. Returns the magnitude of i in base 16.

	if (i < 16L) return 1;
	else if (i < 256L) return 16L;
	else if (i < 4096L) return 256L;
	else if (i < 65536L) return 4096L;
	else if (i < 1048576L) return 65536L;
	else if (i < 16777216L) return 1048576L;
	else if (i < 268435456L) return 16777216L;
	else if (i < 4294967296L) return 268435456L;
	else if (i < 68719476736L) return 4294967296L;
	else if (i < 1099511627776L) return 68719476736L;
	else if (i < 17592186044416L) return 1099511627776L;
	else if (i < 281474976710656L) return 17592186044416L;
	else if (i < 4503599627370496L) return 281474976710656L;
	else if (i < 72057594037927936L) return 4503599627370496L;
	else if (i < 1152921504606846976L) return 72057594037927936L;
	else return 1152921504606846976L;
private static intmagnitude_i(int i)

	if (i < 10) return 1;
	else if (i < 100) return 10;
	else if (i < 1000) return 100;
	else if (i < 10000) return 1000;
	else if (i < 100000) return 10000;
	else if (i < 1000000) return 100000;
	else if (i < 10000000) return 1000000;
	else if (i < 100000000) return 10000000;
	else if (i < 1000000000) return 100000000;
	else return  1000000000;
public static voidmain(java.lang.String[] args)
Test cases. Worth running as
java -verbosegc -ms4000000 jacks.basics.Appender
to see the effects of object creation vs. optimized conversions.

If run this way, note that a garbage collection is run immediately before and after each test, so you see exactly which tests create how many objects. Garbage collections run during a test are due to the test itself creating so many objects that the vm has to reclaim space. Because each test starts with the default empty string buffer, each test will have a large amount of memory to be garbage collected from just a few objects - these are the char arrays inside the StringBuffers being copied over as they expand. What is interesting to note is the difference in objects and space reclaimed between the Appender test and the StringBuffer test.

param
args java.lang.String[]

		long time1, time2;
		boolean[] bools = {true,false,true,false,true,true,false,true,false,false};
		double[] ds = {Double.MAX_VALUE, -3.14e-200D, Double.NEGATIVE_INFINITY, 100,
			567.89023D, 123e199D, -0.000456D, -1.234D, 1e55D, 99999};
		float[] fs = {-3.14F, Float.POSITIVE_INFINITY, 99999, 100,
			567.89023F, 123e33F, -0.000456F, -1.23456789e-2F, 1e-12F, Float.MIN_VALUE};
		long[] ls = {2283911683699007717L, -8007630872066909262L, 4536503365853551745L,
			 548519563869L, 45L, Long.MAX_VALUE, 1L, -9999L, 7661314123L, 0L};
		int[] is = {1147173962, 828789888, -337681747, 940436254, -20385232,
			83, -1154302556, 1975989662, -515020324, Integer.MIN_VALUE};
		char[] cs = {'a", '*", 12345, 9999, Character.MAX_VALUE};
		short[] ss = {Short.MIN_VALUE, (short) 34567, (short) 23, (short) -5555, (short) 256};
		byte[] bs = {Byte.MIN_VALUE, (byte) 99, (byte) 23, (byte) -100, (byte) -11};
		Object[] os = {new Object(), new Object(), new Object()};

		int repeat = 1000;

		main_adj(repeat*100,"booleans",bools,
			"true, false, true, false, true, true, false, true, false, false");
		main_adj(repeat*5,"floats",fs,
			"-3.14F, Float.POSITIVE_INFINITY, 567.89023F, 123e33F, -0.000456F, -1.23456789e-2F, 1e-12F, Float.MIN_VALUE");
		main_adj(repeat*5,"doubles",ds,
			"Double.MAX_VALUE, -3.14e-200D, Double.NEGATIVE_INFINITY,	567.89023D, 123e199D, -0.000456D, -1.234D, 1e55D");
		main_adj(repeat*5,"longs",ls,
			"2283911683699007717L, -8007630872066909262L, 4536503365853551745L, 548519563869L, 45L, Long.MAX_VALUE, 1L, -9999L, 7661314123L, 0L");
		main_adj(repeat*50,"ints",is,
			"1147173962, 828789888, -337681747, 940436254, -20385232, 83, -1154302556, 1975989662, -515020324, Integer.MIN_VALUE");
		main_adj(repeat*500,"chars",cs,
			"'a', '*', 12345, 9999, Character.MAX_VALUE");
		main_adj(repeat*50,"shorts",ss,
			"Short.MIN_VALUE, 34567, 23, -5555, 256");
		main_adj(repeat*50,"bytes",bs,
			"Byte.MIN_VALUE, 99, 23, -100, 245");
		main_adj(repeat*20,"Objects",os,
			"new Object(), new Object(), new Object()");
private static voidmain_adj(int repeat, java.lang.String name, byte[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, char[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, double[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, float[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, int[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, long[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, java.lang.Object[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, short[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
private static voidmain_adj(int repeat, java.lang.String name, boolean[] arr, java.lang.String list)

	long time1, time2;
	StringBuffer s;
	AppenderHelper a = SINGLETON;

	System.out.println("The " + name);
	System.out.println("    " + list);
	System.out.println("are appended to a StringBuffer one by one " + repeat + " times.");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time1 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			a.append(s,arr[j]);
	time1 = System.currentTimeMillis() - time1;
	System.out.println("  The Appender     took " + time1 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("Starting test");
	time2 = System.currentTimeMillis();
	for (int i = repeat; i > 0; i--)
		for (int j = arr.length-1; j >= 0; j--)
			s.append(arr[j]);
	time2 = System.currentTimeMillis() - time2;
	System.out.println("  The StringBuffer took " + time2 + " milliseconds");
	s = new StringBuffer();
	Runtime.getRuntime().gc();
	System.out.println("    For checking purposes, the StringBuffer & Appender output of one iteration is (respectively):");
	for (int j = 0; j < arr.length; j++)
		s.append(arr[j]).append(", ");
	System.out.println("    " + s);
	s = new StringBuffer();
	for (int j = 0; j < arr.length; j++)
		a.append(s,arr[j]).append(s,", ");
	System.out.println("    " + s);
	System.out.println();
public static voidputInAppendMap(AppendConverter h, java.lang.Class c)
Classes needing to add append support for a particular class must add themselves into the append map.

Basically, this means that when an object of class c is passed to the Appender to be appended to the StringBuffer, the AppenderHelper looks up that class in the append map. If there is an AppendConverter object registered for that class, then the task of appending the original object (of class c) to the StringBuffer is delegated to the registered AppendConverter object, by calling it with the method

AppendConverter.appendObj(AppenderHelper a, StringBuffer s, Object o, int depth)

see
appendObj()
param
h the AppendConverter to be registered for the given class.
param
c the class.

	append_map.put(c, h);
public static voidputInAppendMap(AppendConverter h, java.lang.String classname)
Convenience method so that classes can be registered by class name.

see
putInAppendMap(AppenderHelper,Class)
param
h the AppendConverter to be registered for the given class.
param
c the class.

	append_map.put(Class.forName(classname), h);