美文网首页
ArrayList.removeAll() vs HashS

ArrayList.removeAll() vs HashS

作者: lm溪 | 来源:发表于2018-05-09 20:32 被阅读0次

这个东西很多人一看就知道原理,哈哈,无奈在下菜菜一枚,记录下以加深印象吧!有不当之处,欢迎大牛批评指正~

其实看标题就知道二者肯定 HashSet更胜一筹,工作中经常遇到 大数据量的 removeAll()操作,以前习惯性用 list,后来数据量大的时候发现效率极低,下面是一些测试和源码分析。

采用 hashSet 代替 arrayList 进行稍大数据量 removeAll 的场景,依据如下:

a、进行了增量测试,测试数据集范围从 1000-->500000 观察 二者的耗时

数量 arrayList耗时(ms) hashSet耗时(ms)
1000 13 0
10000 491 1
50000 2164 1
100000 44858 7
500000 544184 10

b、看一下二者 removeAll的操作源码

arrayList: A.removeAll(B)

(1) 遍历A

   判断B.contains(A[i])

   若不包含,则 A[w] = A[i]  w从0递增

(2) 遍历完成则将 A[w]往后部分置为 null


(3) 看下上面(1)的B.contains(A[i])的逻辑:

   遍历B,一个个匹配,匹配到则返回B的index
  • 综上,arrayList的removeAll A的循环里面套B的循环,时间复杂度是:O(n*m)

hashSet: A.removeAll(B)

(1)若A.size > B.size 遍历 B

   直接操作A的 hashMap.remove(B[i])   ---- (new hashSet<>时会同步生成对应的hashMap<> key则为set的元素,value为一个虚拟值)

   看下hashMap的remove操作:

   根据B[i] 计算hashcode,根据hashcode 直接在hashMap中找到对应的链表桶,会先定位到链表头,到这相当于直接找到落入的小组,极大缩小了检索范围,然后从链表头开始遍历链表,找到则返回

   java8中对hashMap的链表长度做了优化,当链表长度大于设定的值后,则改链表的数据格式转为'红黑树'--一种遵循类似二叉树的原则:右子树比左子树数据大,但是二叉树容易存在不平衡性,所以红黑树是一种平衡的二叉树

   由于红黑树是顺序性的,基本是二分查找,所以速率大大提升



(2) 若 A.size < B.size 遍历 A

   判断B.contain(A[i])  若true,则直接remove

   进去contain方法,也是直接调用的 hashMap.containsKey(),方法逻辑同上一样
  • 综上,hashSet的removeAll由于通过hashMap的遍历方法实现,时间复杂度是:O(n)

相关文章

网友评论

      本文标题:ArrayList.removeAll() vs HashS

      本文链接:https://www.haomeiwen.com/subject/bcworftx.html