背景
产品让我写一个报表统计某省各地市的红包发放和兑换情况,要求前端显示和写入excel文件的时候全省的记录放在表的第一行。
如图所示
思路
报表统计一般选择用List集合,要在ArrayList和LinkedList中选择一个。
选择要根据具体业务逻辑:
- 先统计各地市的字段再统计全省,全省字段是各地市字段之和。各地市字段结算完后放入List集合中,全省字段统计完后要add到第一个位置。
- 前端显示和写入excel文件的功能一般都是顺序遍历读取List集合中的内容,List的一个元素包含了一个地市的红包发放和兑换情况。
public void exportAsExcel(List<RedPaperExchange> list ){
// 将红包发放和兑换的情况写入excel文件,用于导出
List<RedPaperExchange> list=queryRedPaperExchange();
sheet=excel.createSheet();
for(int i=0;i<list.size();i++){
//往excel的sheet填充数据,伪代码
fillDataIntoExcel();
}
}
private List<RedPaperExchange> queryRedPaperExchange(){
// 查询各地市和全省的红包发放和兑换情况,将结果用于前端显示和写入Excel
List<RedPaperExchange> list=new ArrayList<>(20);
for(){
//先统计各地市的红包发放和兑换情况
list.add(cityRedPaperExchange);
}
//将全省的数据放在第一行
list.add(0, provRedPaperExchange );
return list;
}
那么我们使用的Java集合要满足我们的功能点:
- 前端显示和填充excel文件的过程中都是顺序遍历读取,ArrayList的遍历速度比LinkedList的遍历速度快,因为ArrayList在内存中是连续的,可以降低读取内存的性能开销。
- 全省记录会在统计完之后插入到List的第一个位置,我们知道ArrayList在 list.add(0,element)的时候会将原数组复制出来,然后从第二个位置开始依次安放原数组的元素,最后让 list[0]=element,这本身是很费时的,如果是几千几万个元素的ArrayList要插入一个元素的话,那后面所有元素都要复制,还要扩容的话就更慢了。
而LinkedList基于双向链表实现,可以直接在头部添加新结点,时间复杂度为O(1)
- 一个省的地市大概在20个以内,如果ArrayList以默认初始容量(10)创建的话后面大概需要扩容2次,因此需要在new ArrayList的时候传入initialCapacity=20可以减少扩容次数。而LinkedList扩容不需要数组复制这样费时的操作。
考量的结果:
- ArrayList
优势:
- 顺序遍历集合将数据写入Excel文件的时候速度快(内存连续)
劣势:
- 全省的数据插入到报表第一行的时候就费时间
- 初始容量设定过低的话,某省份地级市多就需要多次扩容
2.LinkedList
优势:
- 将全省数据插入第一行的时间复杂度为O(1),快捷
- 不需要担心扩容
劣势:
- 顺序遍历集合将数据写入Excel文件的效率低,因为链表的空间不连续
最后,虽然看起来LinkedList的优点多一点,但是还是保守选择了ArrayList哈哈。诚然ArrayList插入元素和扩容费时,但初始容量initialCapacity设置得合理的话也能规避多次扩容的风险,而一个包含全省各地市红包兑换记录的ArrayList的大小也不超过50,插入数据带来的时间消耗也可以接受,因此选择了ArrayList。