net.sf.saxon.value
Class FloatingPointConverter

java.lang.Object
  extended bynet.sf.saxon.value.FloatingPointConverter

public class FloatingPointConverter
extends java.lang.Object

This class is derived from AppenderHelper by Jack Shirazi in the O'Reilly book Java Performance Tuning. It is used in Saxon for conversion of doubles and floats to strings, adapted to follow the XPath rules.

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:

(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.


Field Summary
static FloatingPointConverter THE_INSTANCE
           
 
Method Summary
 FastStringBuffer append(FastStringBuffer s, double value)
          Appends the string representation of the double argument to the string buffer.
 FastStringBuffer append(FastStringBuffer s, float value)
          Appends the string representation of the float argument to the string buffer.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

THE_INSTANCE

public static FloatingPointConverter THE_INSTANCE
Method Detail

append

public FastStringBuffer append(FastStringBuffer s,
                               double value)
Appends the string representation of the double argument to the string buffer.

Parameters:
s - the StringBuffer to append the object to.
value - the double to be appended.
Returns:
the FastStringBuffer
See Also:
StringBuffer.append(double)

append

public FastStringBuffer append(FastStringBuffer s,
                               float value)
Appends the string representation of the float argument to the string buffer.

Parameters:
s - the StringBuffer to append the object to.
value - the float to be appended.
Returns:
this AppenderHelper
See Also:
StringBuffer.append(float)