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;
|
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.EvaluationCell;
|
||||||
import org.apache.poi.ss.formula.EvaluationSheet;
|
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
|
* XSSF wrapper for a sheet under evaluation
|
||||||
@ -26,6 +31,7 @@ import org.apache.poi.ss.formula.EvaluationSheet;
|
|||||||
final class XSSFEvaluationSheet implements EvaluationSheet {
|
final class XSSFEvaluationSheet implements EvaluationSheet {
|
||||||
|
|
||||||
private final XSSFSheet _xs;
|
private final XSSFSheet _xs;
|
||||||
|
private Map<CellKey, EvaluationCell> _cellCache;
|
||||||
|
|
||||||
public XSSFEvaluationSheet(XSSFSheet sheet) {
|
public XSSFEvaluationSheet(XSSFSheet sheet) {
|
||||||
_xs = sheet;
|
_xs = sheet;
|
||||||
@ -35,14 +41,46 @@ final class XSSFEvaluationSheet implements EvaluationSheet {
|
|||||||
return _xs;
|
return _xs;
|
||||||
}
|
}
|
||||||
public EvaluationCell getCell(int rowIndex, int columnIndex) {
|
public EvaluationCell getCell(int rowIndex, int columnIndex) {
|
||||||
XSSFRow row = _xs.getRow(rowIndex);
|
// cache for performance: ~30% speedup due to caching
|
||||||
if (row == null) {
|
if (_cellCache == null) {
|
||||||
return 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);
|
||||||
}
|
}
|
||||||
XSSFCell cell = row.getCell(columnIndex);
|
|
||||||
if (cell == null) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return new XSSFEvaluationCell(cell, this);
|
}
|
||||||
|
|
||||||
|
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
|
* Internal POI use only
|
||||||
*/
|
*/
|
||||||
public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
|
public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
|
||||||
|
private XSSFEvaluationSheet[] _sheetCache;
|
||||||
|
|
||||||
public static XSSFEvaluationWorkbook create(XSSFWorkbook book) {
|
public static XSSFEvaluationWorkbook create(XSSFWorkbook book) {
|
||||||
if (book == null) {
|
if (book == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -46,7 +48,21 @@ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EvaluationSheet getSheet(int sheetIndex) {
|
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
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user