重构优化读取合并单元格速度

重构读取合并单元格

重构优化结果

分别计算每张sheet的转换时间和总共需要转换的时间

//优化之前
2020-04-13 15:21:37.921 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 单个sheet转换成对象时间 = 4000
2020-04-13 15:21:38.355 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 单个sheet转换成对象时间 = 4000
2020-04-13 15:21:38.856 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 单个sheet转换成对象时间 = 10000
2020-04-13 15:21:38.856 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 全部转换成对象时间 = 20000

//优化之后
2020-04-13 15:21:37.921 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 单个sheet转换成对象时间 = 720
2020-04-13 15:21:38.355 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 单个sheet转换成对象时间 = 433
2020-04-13 15:21:38.856 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 单个sheet转换成对象时间 = 500
2020-04-13 15:21:38.856 [main] INFO  c.xxx.service.impl.FormatImportServiceImpl - 全部转换成对象时间 = 2139

重构代码

重构之前

在获取合并单元格时需要调用工具类中getMergedRegionValue的方法,之后首先获取sheet中全部合并单元格,并循环判断目标单元格的坐标是否在合并单元格的范围内,如果是则默认返回第一个单元格的值

缺点

  • 每次读取合并单元格的值都需要获取整个sheet表格的合并单元格数据,并对数据进行循环判断,时间复杂度为O(n)

优点

  • 不需要考虑是行合并还是列合并,只要目标单元格在合并的范围内,都可以获取到值
public static String getMergedRegionValue(Sheet sheet, int row, int column) {
    int sheetMergeCount = sheet.getNumMergedRegions();
    for (int i = 0; i < sheetMergeCount; i++) {
        CellRangeAddress ca = sheet.getMergedRegion(i);
        int firstColumn = ca.getFirstColumn();
        int lastColumn = ca.getLastColumn();
        int firstRow = ca.getFirstRow();
        int lastRow = ca.getLastRow();

        if (row >= firstRow && row <= lastRow &&
                column >= firstColumn && column <= lastColumn) {
            Row fRow = sheet.getRow(firstRow);
            Cell fCell = fRow.getCell(firstColumn);
            return getCellValue(fCell);
        }
    }
    return null;
}

重构之后

  • 实际情况中用到列合并情况比较多,所以单独封装一个MergeRegionItem对象

    • 其中包括起始列坐标,结束列坐标,和合并范围内第一个单元格
  • 并添加有参构造方法和判断是否在合并范围内方法

  • 在往上封装一层,将该对象提前预处理,将所有的合并单元格封装进Map集合中

    • key=Integer(合并单元格的行) value=List< MergeRegionItem>(在该行中的合并单元格MergeRegionItem对象的集合)
  • 重构getMergedRegionValue,直接从Map中读取,时间复杂度为O(1)

不足:

  • 目前只能读取列合并范围内的单元格的值,map.put(firstRow, list);只记录了合并单元格的第一行

优点:

  • 预处理存储到Map中再读取,速度大大提升
@Data
public class MergeRegionItem {
    //可以获取列合并范围内的cell
    private int firstColumn;
    private int lastColumn;
    private Cell cell;

    public MergeRegionItem(Row row, CellRangeAddress address) {
        firstColumn = address.getFirstColumn();
        lastColumn = address.getLastColumn();
        cell = row.getCell(firstColumn);
    }

    public boolean isRegion(int col) {
        return firstColumn <= col && col <= lastColumn;
    }
}

public class MergeRegions {
    //Integer--合并单元格的行
    //List -- 在一行中的合并单元格MergeRegionItem对象集合
    private Map<Integer, List<MergeRegionItem>> map;

    public MergeRegions(Sheet sheet) {
        List<CellRangeAddress> addressList = sheet.getMergedRegions();
        map = new HashMap<>();
        for (CellRangeAddress address : addressList) {
            List<MergeRegionItem> list;
            int firstRow = address.getFirstRow();
            if (!map.containsKey(firstRow)) {
                list = new ArrayList<>();
                map.put(firstRow, list);
            } else {
                list = map.get(firstRow);
            }

            list.add(new MergeRegionItem(sheet.getRow(firstRow), address));
        }
    }

    public String getMergedRegionValue(int row, int column) {
        if (map.containsKey(row)) {
            MergeRegionItem item = map.get(row).stream().filter(x -> x.isRegion(column)).findFirst().orElse(null);
            if (item != null) {
                return getCellValue(item.getCell());
            }
        }
        return null;
    }

    public Map<String, Object> getMergedRegionRichText(int row, int column) {
        if (map.containsKey(row)) {
            MergeRegionItem item = map.get(row).stream().filter(x -> x.isRegion(column)).findFirst().orElse(null);
            if (item != null) {
                Map<String, Object> map = new HashMap<>();
                Cell cell = item.getCell();
                CellStyle cellStyle = cell.getCellStyle();
                map.put("cellStyle", cellStyle);
                RichTextString value = cell.getRichStringCellValue();
                map.put("richText", value);
                return map;
            }
        }
        return null;
    }
}

你可能感兴趣的:(重构)