编辑:
那么如何利用 POI 对象的哈希值来缓存和跟踪装饰对象。其他未使用的已创建 CellStyles 将被垃圾回收器丢弃。
这是我们的缓存:
private Map<Integer, MyCellStyle> styleCache = new HashMap<>();
还有我们自己的 CellStyle 类
final class MyCellStyle implements Cloneable {
private XSSFCellStyle xssfCellStyle;
public MyCellStyle(XSSFCellStyle xssfCellStyle) {
this.xssfCellStyle = xssfCellStyle;
}
@Override
public MyCellStyle clone() {
MyCellStyle clone = new MyCellStyle(xssfCellStyle);
return clone;
}
public final MyCellStyle borderLeftMedium() {
MyCellStyle result = clone();
result.xssfCellStyle.setBorderLeft(XSSFCellStyle.BORDER_MEDIUM);
return result;
}
... further decorations
public XSSFCellStyle getXSSFCellStyle() {
return xssfCellStyle;
}
}
现在为了避免创建新对象,我们编写了一个小函数
private MyCellStyle getCellStyle(MyCellStyle targetStyle) {
int targetHash = targetStyle.hashCode();
if (styleCache.keySet().contains(targetHash)) {
return styleCache.get(targetHash);
} else {
return styleCache.put(targetHash, targetStyle);
}
}
然后我们可以像这样创建单元格:
public void createCells() {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
MyCellStyle baseStyle = new MyCellStyle(
(XSSFCellStyle) wb.createCellStyle());
MyCellStyle decoratedStyle = getCellStyle(baseStyle.borderLeftMedium());
cell.setCellStyle(decoratedStyle.getXSSFCellStyle());
}
如果 hashCode 对于 MyCellStyle 对象的相同属性不是唯一的,我们可能必须重写 hashCode 函数:
@Override
public int hashCode() {
return hashValue;
}
并在我们的每个装饰函数中添加样式值:
public final MyCellStyle borderLeftMedium() {
MyCellStyle result = clone();
result.xssfCellStyle.setBorderLeft(XSSFCellStyle.BORDER_MEDIUM);
hashValue += XSSFCellStyle.BORDER_MEDIUM; // simplified hash
return result;
}
=========================
原文:
我喜欢创建装饰方法,将单元格的某个方面添加到单元格样式中。所以首先你创建你的基本样式
public final XSSFCellStyle cellStyleStringBase = wb.createCellStyle();
并创建装饰器方法来创建某种样式
public XSSFCellStyle addBorderLeft(XSSFCellStyle style) {
XSSFCellStyle result = style.clone();
result.setBorderLeft(XSSFCellStyle.BORDER_MEDIUM);
return result;
}
现在,如果你想避免创建新对象,你仍然必须将 cellStyles 保存在自己的变量中,你将无法避免这种情况,但根据我的经验,如果你只是装饰你的单元格,性能就足够了像这样
cell1.setCellStyle(addBorderLeft(cellStyleStringBase);
cell2.setCellStyle(addBorderRight(addBorderRight(cellStyleStringBase));
...
如果你用很多样式来装饰,创建你自己的 CellStyle 类是有意义的
public final MyCellStyle implements Cloneable {
private XSSFCellStyle xssfCellStyle;
public MyCellStyle(XSSFCellStyle xssfCellStyle) {
this.xssfCellStyle = xssfCellStyle;
}
@Override
public MyCellStyle clone() {
MyCellStyle clone = new MyCellStyle(this.xssfCellStyle);
return clone;
}
public final MyCellStyle borderLeftMedium() {
return this.clone().setBorderLeft(XSSFCellStyle.BORDER_MEDIUM);
}
public final MyCellStyle borderRightThick() {
...
}
然后您可以以更易读的方式构建您的样式:
MyCellStyle base = new MyCellStyle(cellStyleStringBase);
cell1.setCellStyle(base
.addBorderLeftMedium()
.addBorderRightThick()
.addBorderBottomThin());
未经测试,但希望对您有所帮助。