接上述文章,这里继续探讨下循环内集合使用怎么优化
先看下原代码:
public static void outsideLoop() { List
上述代码,很容易的就能看出来问题,循环体内初始化,在资源优先的情况下,必然会内存溢出,并且初始化过程本省也是会消耗性能的。我们先看下执行结果(我这里堆内存设置的为300m):
不出意外的OOM了。
优化思路:提取循环内的初始化,再使用完map之后清理map数据。
对于清理map数据得方式有很多种,一个是根据key值remove,第二个直接clear。那我们再来看下打这两者效率对比。
(1)使用remove 清理map数据
public static void outsideLoop() { List
结果:可以看出来已经解决了OOM问题了 ---执行时间:~350ms
(2) 使用clear清理map
public static void outsideLoop() { List
结果:可以看到相同数据量的情况下,clear效率会比remove更好一点的 -- 执行时间:~300ms。
分析过程:
remove源码:可以容易看出来,remove是通过先找到key的节点然后进行删除操作,如果再key比较复杂的情况下,该方式就很耗性能了。
clear源码:这个就是直接根据列表长度将列表进行删除了,不关心树节点的操作。
综合对比:
方式 | 100万 | 500万 | 1000万 | 100万key-60 |
原方式 | 1077ms | OOM | OOM | 10000ms |
使用remove清理map | 77ms | 340ms | 596ms | 923ms |
使用clear清理map | 61ms | 306ms | 518ms | 600ms |
结论:
1、提出循环体内初始化,可以明显的提交性能。
2、再map的key数量较少时,clear和remove方式性能相差不大,但clear等优。
3、数据量很大或者不知时,都推荐使用clear。
4、如果循环后续有其他相关业务时,再完成list集合或者对象使用之后,手动清除list=null, 因为list的生命周期随方法的结束,如果后续逻辑复杂,list会持续占用内存。