总结一下常见的EasyExcel面试题

发布于:2025-04-09 ⋅ 阅读:(36) ⋅ 点赞:(0)

说一下你了解的POI和EasyExcel

POI(Poor Obfuscation Implementation):它是 Apache 软件基金会的一个开源项目,为 Java 程序提供了读写 Microsoft Office 格式文件的功能,支持如 Excel、Word、PowerPoint 等多种文件格式,是 Java 操作 Office 文档的基础工具,发展历史悠久,功能强大且全面

EasyExcel:是阿里巴巴开源的一个基于 POI 进行二次封装的轻量级 Excel 处理框架,主要专注于 Excel 文件的读写操作,简化了 POI 的操作流程


EasyExcel对比POI

功能丰富度

POI:POI 是一个底层的 Java 操作 Excel 的工具包,在进行读写操作时,需要手动处理文件流、解析器、工作表、行和单元格等多个元素

以读取文件为例,需要创建工作簿对象、获取工作表、遍历行和单元格等,代码量较多且逻辑复杂。

对于复杂的操作,如设置单元格样式、合并单元格等,还需要编写更多的代码来实现。这使得使用 POI 进行开发时,代码的复杂度显著增加

EasyExcel

EasyExcel 对常见的 Excel 读写场景进行了高度封装,提供了极为简洁的 API。在读取 Excel 时,只需定义与表格列对应的实体类和监听器


内存占用

EasyExcel 采用基于事件驱动的读写模式,在读写大数据量的 Excel 文件时,逐行处理数据不需要将整个文件加载到内存中。这使得它在处理大规模数据时,内存占用非常低,能够有效避免内存溢出的问题。即使处理包含数百万行数据的 Excel 文件,也能稳定运行

POI 的用户模型 API(如 HSSFXSSF)在处理 Excel 文件时,会将整个文件加载到内存中,当文件数据量较大时,会占用大量的内存资源,容易导致内存溢出。虽然 POI 也提供了事件模型 API(如 SAX 解析器)来处理大数据量文件,但使用起来相对复杂,需要开发人员具备较高的技术水平


读写性能

POI:POI 的用户模型 API 在处理大数据量文件时,由于需要将整个文件加载到内存中,会导致读写效率降低。而事件模型 API 虽然在处理大数据量时性能较好,但需要手动处理事件,开发难度较大,并且在处理一些复杂操作时,效率也会受到一定影响

EasyExcel:由于采用了事件驱动的方式,EasyExcel 在读写数据时,数据处理和文件操作是同步进行的,减少了中间环节,提高了读写效率。特别是在处理大数据量文件时,其逐行处理的方式能够更快地完成读写操作

在处理大数据量的 Excel 文件时,EasyExcel 采用了基于事件驱动的读写模式,逐行处理数据,避免了将整个文件加载到内存中,从而大大降低了内存占用。例如,当需要读取一个包含数百万行数据的 Excel 文件时,使用 POI 的用户模型 API 可能会导致内存溢出,而 EasyExcel 可以稳定地处理这些数据


事件驱动为什么快+安全?

EasyExcel 通过 SAX 事件驱动 + 流式读写,实现了:
超低内存占用(恒定内存,与文件大小无关)。
高效处理大文件(GB 级 Excel 轻松应对)。
避免 OOM(彻底解决 POI 的内存瓶颈)


为什么说EasyExcel的OOM风险小

EasyExcel不需要将整个文件加载到内存中,poi需要加载整个文件?

1. 传统 POI 的 DOM 模式:全量加载

DOM(Document Object Model)
POI 将整个 Excel 文件解析为一个树形结构对象,全部加载到内存中。
类似于把一本书全部复印到脑子里,再逐页阅读

2. EasyExcel 的 SAX 模式:流式逐行处理

SAX(Simple API for XML)
EasyExcel 像流水线一样逐行扫描 Excel 文件,触发事件回调处理数据。
类似于用扫描仪逐页扫描一本书,读一页处理一页,然后立刻扔掉

EasyExcel 的 SAX 模式 通过事件驱动 + 即时丢弃数据(即时刷盘),实现了按需加载,而 POI 的 DOM 模式 为支持复杂功能必须全量加载


EasyExcel如何避免写入OOM?

POI必须是全量写入,这也是它的内存瓶颈

而EasyExcel 默认每处理 2000 行(可配置)就将数据从内存刷入磁盘文件流,即时释放内存
内存占用 ≈ 单批次数据大小(而非全量数据)。例如写入sheet1然后释放sheet1,再写入sheet2,而不用sheet1,sheet2必须一起写入,分sheet页写可以实现资源及时释放


EasyExcel为啥不维护了?对此你怎么看?

核心功能已成熟,暂无重大特性新增需求。以修复 Bug 和兼容性更新为主,而非频繁发布新功能

开发者资源转移,阿里内部可能将资源投入其他更高优先级项目(如 Spring Cloud Alibaba),开源团队依赖社区贡献,但核心开发者时间有限


面试回答思路引导

面试回答

poi是apache的开源项目,功能非常丰富,而EasyExcel是基于poi的二次简化封装,简化了poi的操作,方便使用

主要让写入和写出更加简单,没必要去操作很多的细节,例如不需要手动编写输入输出流,手动关闭输入输入流的资源,编写解析器等

EasyExcel只需要只需定义与表格列对应的实体类监听器

EasyExcel主要解决的poi的内存瓶颈和读取效率问题

poi使用的是传统的全量加载,而EasyExcel是流失加载,也就是事件驱动+及时刷盘

poi读取的时候,必须要把整个文件加载到内存中读取

poi写入的时候必须一次性全量写入

而EasyExcel读取的时候是流式读取,逐行扫描,读取完的数据从内存中扔掉,不占用内存

EasyExcel写入的时候是流式写入,我们分sheet页写入,这个sheet页写入完就及时释放资源,实现及时刷盘不占用内存

这是他们的区别,也是基于poi的重点优化,poi因为是全量读取和写入逻辑所以oom的概率会非常大

EasyExcel是写完sheet页就释放不会一直占用内存,所以oom的概率小,但这并不说明不会出现oom问题了,使用EasyExcel的时候还是需要严格控制sheet页的,因为sheet页是存到一个List<>中的,如果sheet页过大仍然会导致oom问题


常用的方法

EasyExcel.read()

EasyExcel.write()

WriteSheet sheet = EasyExcel.writerSheet("批次").build() 构造sheet页

ExcelWriter writer = EasyExcel.write(filePath).build() 构造用来写入的ExcelWriter

writer.write(excels, sheet) 把Sheet页放到ExcelWriter里面,然后写入我们传入的内容excels列表

    @Test
    void allData(){
        List<Excel> excels = excelMapper.selectAllOrderById();
        String filePath = "C:\\Users\\ziJian.zheng\\IdeaProjects\\Kira-Test\\src\\main\\resources\\templates\\test.xlsx";
        WriteSheet sheet = EasyExcel.writerSheet("批次" ).build();
        //用来写入的ExcelWriter
        ExcelWriter writer = EasyExcel.write(filePath).build();
        writer.write(excels, sheet);

    }

常见的注解

@ExcelProperty(value = "用户姓名",index = 0)

效果:index属性可以指定当前字段对应excel中的哪一列,可以根据列名value去匹配,也可以不写

如果不使用@ExcelProperty注解,成员变量从上到下的顺序,对应表格中从左到右的顺序

@ExcelIgnore

读写的时候会忽略该字段

@DateTimeFormat 日期转换

日期格式转换:将 Excel 中的日期格式数据(如 2023-01-01)与 Java 字段(StringDate)自动转换

@DateTimeFormat("yyyy-MM-dd")  // 格式化为"2023-01-01"
private String createDate;

@NumberFormat 数字格式转换

将 Excel 中的数字(如 1,000.50)与 Java 字段(String 或数值类型)自动转换

@NumberFormat("#,##0.00")  // 格式化为"1,000.50"
private String price;

@ExcelIgnoreUnannotated

制类字段的默认行为:标注在类上,决定未加 @ExcelProperty 的字段是否参与读写。

不标注该注解:所有字段(无论是否有 @ExcelProperty)都会参与读写。

标注该注解:只有显式标注 @ExcelProperty 的字段参与读写


网站公告

今日签到

点亮在社区的每一天
去签到