Skip to content

3 大数据量导出

guanquan.wang edited this page Nov 7, 2022 · 16 revisions

前面已经展示了简单的导出示例,例子中大部分都传入一个数组,但是我们知道对于十万级、百万级的数量,不可能一次拉取到内存,此时分片功能就突现价值了。

自动分片

ListSheet和ListMapSheet默认支持分片,我们只需要覆写protected List<T> more()方法即可。

下面代码将展示如何分页拉取学生数据,每次拉取1024条数据,这样内存中最多也就1024条数据,边写边拉取数据,直到返回空数组或者null。

new Workbook().addSheet(new ListSheet<Student>() {
    private int pageNo = 0, limit = 1024;
    @Override
    protected List<Student> more() {
        return service.getPageData(++pageNo, limit);
    }
}).writeTo(defaultTestPath);

得益于EEC的Worksheet默认分页,我们无需更多的处理,上面代码即可支持百万级、千万级数据导出

如下代码测试200w随机数字导出的示例

// 导出200w数据
final int loop = 2000;
new Workbook("200w").addSheet(new ListSheet<E>() {
    int n = 0; // 页码
    @Override
    public List<E> more() {
        return n++ < loop ? data() : null;
    }
}).writeTo(Paths.get("d:/"));

// 生成测试数据
public List<E> data() {
    List<E> list = new ArrayList<>(1000);
    for (int i = 0; i < 1000; i++) {
        E e = new E();
        list.add(e);
        e.nv = random.nextInt();
        e.str = getRandomString();
    }
    return list;
}

// 测试对象
public static class E {
    @ExcelColumn
    private int nv;
    @ExcelColumn
    private String str;
}

跑上面的测试代码共耗时11.5s,打开文件效果如下:

第一页共写入1048576行,这也是xlsx格式单页最大行数

page 1

写满第一页后自动新增一个worksheet并写入剩余数据951426,共计200w+2(2个表头)

page 2

读取分片数据

对于自动分片数据,我们不需要一个sheet,一个sheet读取,而是直接使用Stream的flatMap功能将worksheet降维处理,如下代码统计200w数据中数字大于1w的个数

try (ExcelReader reader = ExcelReader.read(Paths.get("d:/200w.xlsx"))) {
    long count = reader.sheets().flatMap(Sheet::dataRows).map(row -> row.too(E.class)).filter(e -> e.nv > 10000).count();
    System.out.println("共计" + count + "个数大于1w");
}

贴出DEBUG日志

- File type: XLSX
- Unzip file to:C:\Users\WANGGU~1\AppData\Local\Temp\eec+431216877215304835
- Finished decompress. start to check the file integrity.
- Size of SharedString: 0
- load C:\Users\WANGGU~1\AppData\Local\Temp\eec+431216877215304835\xl\worksheets\sheet1.xml
- Dimension-Range: A1:B1048576
- end of file.
- load C:\Users\WANGGU~1\AppData\Local\Temp\eec+431216877215304835\xl\worksheets\sheet2.xml
- Dimension-Range: A1:B951426
- end of file.
共计999601个数大于1w
- Count: 0, uniqueCount: 0, Repetition rate: 0.0%
- Forward: 0, Backward: 0, SST: 0, Hot: 0, Tester: {Resize: 0, Size: 0}

通过DEBUG日志可以看到使用flatMap解析完sheet1后接着解析sheet2,得出结果999601,与excel筛选出的结果一致

filter 1 filter 2

Clone this wiki locally