poi SXSSFWorkbook大数据量导出实践
最近公司做一个生成审批附件的功能,算是对老的功能的一个改造,之前使用的XSSF 和HSSF ;但是一旦数据量超过万级别了,导出的性能就差强人意了;要想快那就必须要要用到poi的SXSSFWorkbook了;
用到的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>29.0-jre</version> </dependency>
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
|
示范代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| public class TestPoi {
public static void main(String[] args) throws Exception{ Long start = System.currentTimeMillis(); List<UserInfo> userInfoList =new ArrayList<>(); for(int i=1;i<=20*10000;i++){ UserInfo userInfo = new UserInfo(); userInfo.setId(Long.getLong(Integer.toString(i))) .setName("echo"+i) .setPassword(UUID.randomUUID().toString()); userInfoList.add(userInfo); } String fileUrl = "/Users/echo/Desktop/testExcel.xlsx"; FileInputStream fs; FileOutputStream os = null; try { File excel=new File(fileUrl); fs=new FileInputStream(excel); XSSFWorkbook workbook = new XSSFWorkbook(fs); SXSSFWorkbook wb = new SXSSFWorkbook(workbook,1000); Sheet sheet1 = wb.getSheetAt(0); int excelRow = 1;
List<List<UserInfo>> reParam = Lists.partition(userInfoList, 1000); for (int x = 0;x<reParam.size();x++) { List<UserInfo> userInfos = reParam.get(x); for (int j = 0; j < userInfos.size(); j++) { Row contentRow = sheet1.createRow(excelRow++); Cell cell0 = contentRow.createCell(0); cell0.setCellValue(userInfos.get(j).getPassword());
Cell cell1 = contentRow.createCell(1); cell1.setCellValue(userInfos.get(j).getName()); Cell cell2 = contentRow.createCell(2); cell2.setCellValue(userInfos.get(j).getPassword()); } } os = new FileOutputStream(fileUrl); wb.write(os); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } } catch (IOException e) { e.printStackTrace(); } } System.out.println("导20万数据耗时:"+(System.currentTimeMillis()-start)); } }
|
总结
SXSSFWorkbook 有个缓存区,所以上面定义为1000,后面的数据就需要按1000拆分写到excel中,如果不设定此值有可能OOM,按1000拆分后,注意创建行的行号就行了!