集合类的特点:各个集合类的对比;
集合类的构造方法与API;
集合类的源码;
1.1特点
1.Collection是Collection集合体系的顶级接口
2.Collection有些子实现是有序的,有些子实现是无序的
3.Collection有些子实现允许存储重复元素,有些子实现不允许存储重复元素
4.collection有些子实现可以存储null,有些不可以
接口:定义规范
一个接口是另外一个接口的子接口:子接口想在父接口的定义上进行增强;
一个子类是另一个类的子类:复用,复用父类的参数变量以及方法;
removeAll:去交集
addAll:合集
retainAll:留并集
toArray 转数组;
1.21 toArray
注意:toArray虽然是一个泛型方法,但是在进行转化数组的时候要考虑到原来集合中所存储的元素;
集合里面已经有数据,
集合.toArray(T[])
注意2.如果我们给定的数组足够大,toArray会返回原来的数组;
注意3.如果数组不够大(不能存储集合类的所有元素),那么返回的不是一个数组,只是返回数组包涵所有集合元素
注意4.如果我们给的参数数组过大,那么这个数组前的n个位置存储原来集合中的数据,n+1位置变为null,其余不变;
(在底层创建一个数组,把集合中的数组传进去,所有的集合类都具有这个方法)
--
1.2.2iterator
集合接口Cellection定义了一个方法,以时间维度n返回一个iterator类型的对象;
该方法并不复制数据,而是依赖原数据进行遍历;(foreach而不是);
注意:遍历之前不能进行删除;(并修异常)
不能进行连续的删除(指针)
为什么iterator是一个接口:
Collection是一个接口,没有实体结构,而其子类才是数据存储的真正实现者,但是每一个Collection子实现都存在差异,也就意味着每一个子实现接口的遍历方式肯定不同,也就意味着每一个子实现都会维护一个自己的遍历方式;所以继承了迭代器的接口来为每一个子实现来定义规范;
1.2.2.1 并发修改异常:ConcurrentModificationException
由于我们不想在某些集合类上加锁来保证数据同步(加锁会导致效率降低),所以在为了多线程情况下避免一个情况出现,一个线程在遍历,另一个线程在进行添加删除(这会导致遍历失去意义),所以我们在某些集合类中维护了一个modCount参数,以保证同步问题(如果原集合数据被别人修改,那么当前遍历会检测到modCount变化,而报出异常);
但是由于设计不够完美.会导致在单线程情况下啊,如果同时在进行iterator迭代一边使用原集合类的添加删除方法修改原集合数据,也会导致modCount不同步会导致异常;
(删除也用迭代器删除就行了)
2.foreach
iter快捷键
底层就是iterator方法
对数组遍历的时候会转化为fori
有序:可预期的位置(而hash算出的是不预期的所以说是无序)
API
1.根据下标添加
add(index i , element , e)
addAll(index i , element , e)
2.根据下标获取下标对应内容
E get(int index)
3.返回根据内容出现下标/最后位置的下标
int IndexOf()
int LastIndexOf()
//toArrey的三种情况((类型)数组长度小于,相等,大于)(list.toArrey(arr))
ListIterator 增加了几个方法
1.boolean hasPrevious() 向前是否有元素可以遍历
2.E previous() 向前遍历
3.void add(E e) 添加到当前位置
4.void set(E e) 修改是刚刚遍历过的元素位置
5.int nextIndex()返回下一个遍历下标
6.int previousIndex()返回下一个遍历下标
逆序遍历
视图
视图的本质:自己并不维护数据仅仅是维护一些标记指向某些数据;
subList,返回的一个视图,对视图的修改会影响到原始的数据
(在方法中调用了this的remove方法来进行删除,因此修改影响this的数据了)
而在that= this.sublist(0,index)之后对原来数据(this)进行修改后,同时对that修改也会并发修改异常;
-------
2.ArrayList
1.ArarryList是list的具体子实现
2.ArarryList描述的是一个线性表
3.ArarrtList的底层结构是一个数组
4.ArrayList的底层数组默认长度10,扩容1.5(1+>>1)
5.ArrayList有序
6.ArrayList允许重复
7.ArrayList允许存储null
8.ArrayList线程不安全>>1
源码分析-->1.默认长度10的数组(懒加载(add的时候运行)),扩容1+(>>1)),重新建立新的数组然后复制过去
API:
(
removeAll:去交集
addAll:合集
retainAll:留并集
toArray 转数组;
toArray
add(index i , element , e)
addAll(index i , element , e)
E get(int index)
int IndexOf()
int LastIndexOf()
)
void ensureCapacity(int minCapacity)(增加容量的方法,因为每次增加都是1.5倍,所以每次扩容只是至少参数值这么大(不用记))
void trimTosize();将数组trim到原来数组中的elementsize(不用记)
Object clone()返回此ArrayList实例的浅表副本(类似浅克隆)
subArreyList() 和上面一样的视图方法
迭代器源码分析
调用迭代器的删除,删除掉这个位置的元素之后
cursor 和 lastRet都会回到0与-1而重新进行遍历,所以只要是a就会全部都删除掉,反复遍历了属于是;
3.Vector
1.Vectorw List的一个具体子实现
2.Vector是一个线性表
3.Vector底层是一个数组
4.Vector初始容量10与扩容机制(如果在构造器填写了增量,那么增加增量,如果为0扩大为原来的2倍)
5.Vector有序,可重复,允许null
6.线程安全
5.LinkedList
5.1特点:链表的线性表
作为队列和栈使用
set构造方法转成set
API
LinkedList特有:
---双向链表的方法---
--队列的方法--
--栈--
pop
push
peek
---
区别:共同点:都是List子实现,线性表
List还是Dque子实现可以做:队列,栈
都是有序,可以重复,不安全,可以存null
数组与链表不同:查找和修改的效率
ArarryList API少一点