首页 > 编程知识 正文

map集合和collection集合的区别

时间:2023-05-03 17:06:11 阅读:220097 作者:4142

ArrayList与Set的contains方法的时间复杂度 contains方法的时间复杂度Collection集合中的list和set集合listset

contains方法的时间复杂度

集合在我们的开发过程中是经常使用的,本篇文章主要讲解集合的判断功能的时间复杂度。

Collection集合中的list和set集合 list

1.我们以ArrayList为例。查看ArrayList的Contains()方法的源码,contains()方法调用的是自身的indexOf()方法,继续跟进代码

2.我们可以看到其实Arraylist的底层实现是数组,contains()方法就是拿需要判断的元素和数组elementDatap[]中的元素一一进行比较,因此时间复杂度为n(一次判断),对于Arraylist中元素比较少的情况下使用contains()方法还算ok,但是对于10万级以上的数据,显然contains()方法还是非常耗费时间的,稍后会贴出代码进行分析。

3.这里有一个关于序列化和反序列化的小插曲,感兴趣的可以浏览一下,不感兴趣的直接跳过3,4,5,6。我们看一下elementData[]这个数组,我们发现这个数组用关键字transient修饰的,ArrayList类实现了序列化(Seriliable)的接口,也就表明ArrayList类是可以序列化的,而transient修饰的变量在序列化的时候是不能被序列化的。elementData[]这个数组是用来存放ArrayList中的元素的,
4.如果不能被序列化,那么序列化之后的ArrayList是否会丢失这些元素呢?那我们要看一下具体的序列化与反序列化的实现了。

5.从上面的代码中我们可以看到在序列化的时候将集合的大小以及elementData[]数组中有值的部分写入了ObjectOutputStream,在反序列化的时候从ObjectInputStream获取size以及相应的element,再恢复到elementData[]数组中去。既然最后还是要反序列化出elementData[]数组,为什么不将elementData[]数组设置为可以序列化的呢?这就涉及到了ArrayList的扩容机制。

6.由于扩容机制是增长1.5倍(至于为什么是1.5请自行百度),假设当前容量是10,所需容量是11,那么扩容后elementData[]数组容量是101.5=15,所以会有4个元素空间的浪费,因此如果将elementData[]数组进行序列化,那么就会导致空间的浪费!
7.好了,扯远了,言归正传!刚刚说到ArrayList的contains()方法性能测试,下面分别对容量为一万和10万的容量进行测试contains()方法供消耗的时间(代码其他部分执行时间忽略且所需判断的元素个数与存放的元素个数相等)


从上图可以看到1万乘1万还可以,但是10万10万的时候大概需要半分钟。LinkedList底层实现原理也一样

set

1.以HashSet为例,HashSet底层是使用HashMap实现的。

2.而HashMap的containskey()方法的底层实现原理是依据hash()和equals()方法,首先要根据key计算出对应的哈希值(时间复杂度为o(1))并与hash表中的值相比较,不同就继续比较,相同则再比较元素是否相同,二者都相同则得到的是true,否则说明Map中没有这个key。

3.因此,HashSet的contains()的时间复杂度为o(1)~o(n),主要看相同的hash值的元素有多少个。
下面进行性能测试一下,我们只用10万的数据来测

4.可以看到只需要20ms(循环执行的时间忽略)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。