第四天 Java中的集合Collection

今天我们来看一下Collection集合
我们知道Collection里面主要包括了List 和Set两种
List中我们常用的有:ArrayList, LinkedList
Set中我们常用的有:HashSet, treeSet, TreeSet
下面我们来挨个的看看 这些底层都是什么 ,怎么操作的
 
ArrayList
我们先来看看 ArrayList的声明

里面很简单 ,就是一个Object[]的数组,出事容量为10

然后我们来看一下添加操作

可以看到add方法很简单,先判断是否有扩容,然后直接size++把数据添加到数组,而且这个操作是无锁的,所以也不是线程安全的

扩容条件就是 size + 1是否大于elementData.length
扩容数据是elementData.length+elementData.length/2 每次扩容,容量增加一半,但是我们知道这个add不是线程安全的,如果一个线程来添加数据没有问题,扩容也没有问题
但是多线程的时候就不行了 ,有可能出现扩容一半还是不能放下多线程同时添加的数据,所以扩容还有个规则,就是判断 elementData.length+elementData.length/2发现扩容一半还是小于 size+1 那就按照我们传递的扩容

ArrayList添加数据步骤【上面我们看到这个add是无锁操作,所示不是线程安全的】

第一步:先判断是否需要扩容
第二步:如果扩容,分三种情况,第一种:按照原始数组容量的一半扩容,第二种:按照我们传递的值扩容【多线程并发可能会出现】,第三种:直接最大容量扩散int的最大值
第三步:在object[]数组中 size++添加数据

LinkedList
然后我们再来看看 LinkedList这个底层是什么

我们看到LinkenList的底层是Node,那么Node有是什么那

很简单一个 双写的链表,那么我们来看看这个LinkedList的add方法是怎么工作的

 

 

我们可以看到Add方法其实很简单【链表是无锁操作所以不是线程安全的】

第一步:先拿出尾节点
第二步:创建新节点
第三步:把新节点赋值给尾节点
第四步:判断链表有没有数据,
第五步:如果没有数据,就把新节点作为第一个数据加入链表
第六步:如果有数据把新节点添加到链表尾部,然后size++【查询的时候很有用】
下面我们来看看 查询方法Get

 

 

Get操作就更清晰了,给出一个index然后去链表循环,但是我们知道 链表查询的时间复杂度是 0(n)的,所以数据越多查询越慢,所以这里使用了二分法查找

第一步:判断我们要查询的index是否小于链表容量的一半,
第二步:如果小于容量的一半就从链表头部循环查找
第三步:如果大于容量一半就从链表尾部循环查找

HashSet
我们现在来看一下 HashSet的源码是怎么操作的

很明显HashSet的底层就是一个hashMap,上一章我们总结了HashMap的底层就是一个数组+链表而且不是线程安全的

HashSet的添加方法就更简单了

直接就是HashMap的Put,只是添加的时候吧val添加成了一个固定的Object然后做了一个比较,

但是HashSet实现了Set,Set实现了Collection所以HashSet可以 iterator
HashSet 相对于List他是无序的,相对于Map他是可以iterator的,能foreach,并且它的val是一个默认的Object

TreeSet
 

很明显TreeSet底层就是一个 TreeMap,我们知道TreeMap底层是一个黑红树,所以TreeSet底层也是一个树

添加方法add也是直接调用了TreeMap的add,只是吧val添加成了一个默认值了

但是TreeSet底层是TreeMap 所以TreeMap有序,而且实现了Collection 所以是iterator,也就是说可以foreach

LinkedHashSet

很明显LinkedHashSet的底层是LinkedHashMap,而LinkenHashMap的底层是:双向链表+HashMap

所以LinkedHashSet的数据是有序的,而且因为实现了Collection 所以可以foreach

 
总结:
ArrayList:属于List不是线程安全的,底层是数组,添加数据前会先判断扩容,扩容分为三种方式 1:扩容量为原始容量的一般, 2:根据我们传递的值扩容【多线程并发原因前面我们说过】 3:最大容量扩容
LinkedList :属于List不是线程安全的,底层是一个双向的链表,添加就是常规链表添加,只有在查找的时候根据我们查找的index 和容量/2做比较使用提升查找效率
HashSet :属于Set不是线程安全的,底层是HashMap,只是在put的时候吧val设置为了一个固定的Object,因为实现了Collection 所以可以迭代
TreeSet:属于Set不是线程安全的,底层是TreeMap,只是在put的时候吧val设置为了一个固定的Object,因为实现了Collection 所以可以迭代
LinkedHashSet :属于Set不是线程安全的,底层是LinkenHashMap只是在put的时候吧val设置为了一个固定的Object,因为实现了Collection 所以可以迭代
 
 

posted @ 2022-03-16 19:36  瀚海行舟  阅读(22)  评论(0)    收藏  举报