java.util.Collection源码分析与深度理解
写在开头
java.util.collection 作为java开发最常用的接口之一,我们经常使用,今天我带大家一起研究一下collection接口,希望对大家以后的编程以及系统设计能有所帮助,本文所研究的jdk版本为jdk1.8.0_131
明确一下几点:
- collection是接口,其继承了iterable接口
- collection属于单值类型集合,重点子接口list接口和set接口
java.util.list接口(有序、不唯一)
arrarylist
arraylist 是一个数组队列,相当于 动态数组。与java中的数组相比,它的容量能动态增长。它继承于abstractlist,实现了list, randomaccess, cloneable, java.io.serializable这些接口。arraylist是非同步的,效率高但是线程不安全,collections.sychromiziedlist(new arrarylist<>());
可以让那个arraylist变成线程安全类
- arraylist是基于动态数组实现的,在增删时候,需要数组的拷贝复制。
- arraylist的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
- 删除元素时不会减少容量,若希望减少容量则调用
trimtosize()
- 它不是线程安全的。它能存放null值。
linkedlist
linkedlist是一个双向循环列表队列
- linkedlist 是一个继承于abstractsequentiallist的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
- linkedlist 实现 list 接口,能对它进行队列操作。
- linkedlist 实现 deque 接口,即能将linkedlist当作双端队列使用。
- linkedlist 实现了cloneable接口,即覆盖了函数
clone()
,能克隆。 - linkedlist 实现
java.io.serializable
接口,这意味着linkedlist支持序列化,能通过序列化去传输。 - linkedlist 是非同步的。
vector
底层是数组,现在已少用,被arraylist替代,原因有两个:
- vector所有方法都是同步,有性能损失。
- vector初始length是10 超过length时 以100%比率增长,相比于arraylist更多消耗内存。
- 参考资料:https://www.zhihu.com/question/31948523/answer/113357347
总的来说:查询多用arraylist,增删多用linkedlist。
arraylist增删慢不是绝对的(在数量大的情况下,会有例外):
- 如果增加元素一直是使用
add()
(增加到末尾)的话,并且不扩容的情况下) - 一直删除末尾的元素也是arraylist要快【不用复制移动位置】
- 至于如果删除的是中间的位置的话,还是arraylist要快!
但一般来说:增删多还是用linkedlist,因为上面的情况是极端的~
java.util.set接口(无序、唯一)
|——sortedset接口——treeset实现类
set接口——|——hashset实现类
|——linkedhashset实现类
hashset
hashset底层基于hashmap实现,如图
hashset中的add()方法,是将对象e放入hashmap中的key的位置,value位置存放的是一个固定的object,如图:
hashset是无序唯一的,当元素为自定义对象时,两者的hashcode不同,被认为是不同的元素从而被允许放入hashset中,但这不符合实际的生产意义,因此需要让其判定位相等,就要重写hashcode()
,然而重写hashcode()
,会出现重码的bug,因此需要重写equals()
来解决
添加元素的时候,如果key(也对应的set集合的元素)相等,那么则修改value值。而在set集合中,value值仅仅是一个object对象罢了(该对象对set本身而言是无用的)。
也就是说:set集合如果添加的元素相同时,是根本没有插入的(仅修改了一个无用的value值),从源码(hashmap)中也看出来,==和equals()
方法都有使用,具体过程如下
- 新元素的hsah是否等于老元素的hash,如果不相等,则元素不同,如果相等,那么进行第二部比较
- 新元素与老元素用“==”进行比较,如果相等,则为同一元素,若不同则进行第三部比较
- 新元素和老元素用
equals()
方法判定是否相等,如果不等则不是同一元素,如果相等那么结果为:两个元素不是同一个对象,程序想把它们当成同一个对象,因此重写了equals方法;
treeset
与hashset是基于hashmap实现一样,treeset同样是基于treemap实现的。
treeset是sortedset接口的唯一实现类,treeset可以确保集合元素处于排序状态。treeset支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向 treeset中加入的应该是同一个类的对象。
linkedhashset
linkedhashset是hashset的一个“扩展版本”,hashset并不管什么顺序,不同的是linkedhashset会维护“插入顺序”。hashset内部使用hashmap对象来存储它的元素,而linkedhashset内部使用linkedhashmap对象来存储和处理它的元素
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
推荐阅读
-
java.util.Collection源码分析与深度理解
-
Spring源码深度解析(四)——模拟mybatis和原理分析
-
Spark源码系列(四) DAGScheduler源码分析与Task最佳位置算法源码
-
深入理解PHP之源码目录结构与功能说明
-
java.util.Collection源码分析与深度理解
-
《机器学习实战》3.决策树算法分析与源码实现
-
Spring Cloud动态配置实现原理与源码分析
-
「DUBBO系列」责任链模式实现原理与源码分析
-
对”const“和”static“的深度理解—预处理、const、static与sizeof(二)
-
spring5 源码深度解析----- AOP目标方法和增强方法的执行(100%理解AOP)