Java; POI Optimization - Speeding up the RecordFactory class.
This optimization needs two posts. This post presents a class that maps short values to a Constructor
object.
The RecordFactory class maps the short id value in the Excel file to a Java class. In the current version
of POI, that relationship is kept, quite logically, in a Map object. However, using a Map
object required that the short value be converted into a Short object quite frequently. This conversion is
inefficient and, if some specially coding is done, unneeded. Note that the following class,
shortToConstructorCache, is derivative of my earlier shortShortCache class.</p>
/**
* Cache a mapping from a short value to a Constructor object.
*
* This class is designed to optimize the RecordFactory.createRecord()
* method. It might be useful in other contexts, but I did not check.
*/
public class shortToConstructorCache {
/**
* The number of entries in the cache.
*/
protected int distinct;
/**
* The cached short values.
*/
private short table[];
/**
* The cached constructor methods
*/
private Constructor values[];
/**
* RecordFactory uses a statically created array of
* classes to initialize the cache and the entries
* in the cache are never changed nor added to.
*/
public shortToConstructorCache(Class[] records) {
super();
this.table = new short[records.length];
this.values = new Constructor[records.length];
Constructor constructor;
for (int i = 0; i < records.length; i++) {
Class record = null;
short sid = 0;
record = records[i];
try {
sid = record.getField("sid").getShort(null);
constructor = record.getConstructor(new Class[] {short.class, short.class, byte[].class});
} catch (Exception illegalArgumentException) {
illegalArgumentException.printStackTrace();
throw new RecordFormatException("Unable to determine record types");
}
if (constructor == null) {
throw new RecordFormatException("Unable to get constructor for sid [" + sid + "].");
} else {
this.table[this.distinct] = sid;
this.values[this.distinct] = constructor;
this.distinct++;
}
}
}
/** Gets the Constructor object related to a given
* key.
*/
public Constructor get(short key) {
Constructor rv = null;
for (int i = 0; i < this.distinct; i++) {
if (this.table[i] == key) {
rv = this.values[i];
}
}
return rv;
}
/** Returns the number of entries in the cache. */
public int size() {
return this.distinct;
}
/** We're breaking encapsulation but some code in RecordFactory
* wants the information and I want to change RecordFactory as
* little as possible.
*/
public short[] getTable() {
return this.table;
}
}