bug 57840: cache XSSFEvaluationCell and XSSFEvaluationSheet instances (30% evaluation speedup due to caching and faster cell lookup); patch from Greg Woolsey
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1747838 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6d03eafcfe
commit
e3beb3abdd
@ -17,8 +17,13 @@
|
||||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.ss.formula.EvaluationCell;
|
||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
|
||||
/**
|
||||
* XSSF wrapper for a sheet under evaluation
|
||||
@ -26,6 +31,7 @@ import org.apache.poi.ss.formula.EvaluationSheet;
|
||||
final class XSSFEvaluationSheet implements EvaluationSheet {
|
||||
|
||||
private final XSSFSheet _xs;
|
||||
private Map<CellKey, EvaluationCell> _cellCache;
|
||||
|
||||
public XSSFEvaluationSheet(XSSFSheet sheet) {
|
||||
_xs = sheet;
|
||||
@ -35,14 +41,46 @@ final class XSSFEvaluationSheet implements EvaluationSheet {
|
||||
return _xs;
|
||||
}
|
||||
public EvaluationCell getCell(int rowIndex, int columnIndex) {
|
||||
XSSFRow row = _xs.getRow(rowIndex);
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
XSSFCell cell = row.getCell(columnIndex);
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
return new XSSFEvaluationCell(cell, this);
|
||||
// cache for performance: ~30% speedup due to caching
|
||||
if (_cellCache == null) {
|
||||
_cellCache = new HashMap<CellKey, EvaluationCell>(_xs.getLastRowNum()*3);
|
||||
for (final Row row : _xs) {
|
||||
final int rowNum = row.getRowNum();
|
||||
for (final Cell cell : row) {
|
||||
// cast is safe, the iterator is just defined using the interface
|
||||
final CellKey key = new CellKey(rowNum, cell.getColumnIndex());
|
||||
final EvaluationCell evalcell = new XSSFEvaluationCell((XSSFCell) cell, this);
|
||||
_cellCache.put(key, evalcell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _cellCache.get(new CellKey(rowIndex, columnIndex));
|
||||
|
||||
}
|
||||
|
||||
private static class CellKey {
|
||||
private final int _row;
|
||||
private final int _col;
|
||||
private final int _hash;
|
||||
|
||||
protected CellKey(int row, int col) {
|
||||
_row = row;
|
||||
_col = col;
|
||||
_hash = (17 * 37 + row) * 37 + col;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
// assumes other object is one of us, otherwise ClassCastException is thrown
|
||||
final CellKey oKey = (CellKey) obj;
|
||||
return _row == oKey._row && _col == oKey._col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ import org.apache.poi.ss.formula.ptg.Ptg;
|
||||
* Internal POI use only
|
||||
*/
|
||||
public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
|
||||
private XSSFEvaluationSheet[] _sheetCache;
|
||||
|
||||
public static XSSFEvaluationWorkbook create(XSSFWorkbook book) {
|
||||
if (book == null) {
|
||||
return null;
|
||||
@ -46,7 +48,21 @@ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
|
||||
|
||||
@Override
|
||||
public EvaluationSheet getSheet(int sheetIndex) {
|
||||
return new XSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
|
||||
// Performance optimization: build sheet cache the first time this is called
|
||||
// to avoid re-creating the XSSFEvaluationSheet each time a new cell is evaluated
|
||||
// EvaluationWorkbooks make not guarentee to syncronize changes made to
|
||||
// the underlying workbook after the EvaluationWorkbook is created.
|
||||
if (_sheetCache == null) {
|
||||
_sheetCache = new XSSFEvaluationSheet[_uBook.getNumberOfSheets()];
|
||||
for (int i=0; i < _uBook.getNumberOfSheets(); i++) {
|
||||
_sheetCache[i] = new XSSFEvaluationSheet(_uBook.getSheetAt(i));
|
||||
}
|
||||
}
|
||||
if (sheetIndex < 0 || sheetIndex >= _sheetCache.length) {
|
||||
// do this to reuse the out-of-bounds logic and message from XSSFWorkbook
|
||||
_uBook.getSheetAt(sheetIndex);
|
||||
}
|
||||
return _sheetCache[sheetIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user