Map集合与Collection集合的contains方法的时间复杂度

ArrayList与Set的contains方法的时间复杂度

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(循环执行的时间忽略)

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值