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; } }