net.sf.saxon.value
Class FloatingPointConverter
java.lang.Object
net.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:
- 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.
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
THE_INSTANCE
public static FloatingPointConverter THE_INSTANCE
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)