ArryList
ArryList是List接口的可变数组非同步实现,包括null在内的所有元素
底层采用数据实现
该集合是可变长度数组,数组扩容是,会将老数组的元素重新考呗一份到新数组中,每次数据赠量大学是其容量的1.5倍
RandomAccess 实现接口,for循环最快
线程不安全 ,替换方式为Vector,Vector方法都加了synchronized关键字,效率慢
替换方式为Collections.synchronizedList(new ArryList)
LinkedList
链表,双向链表
添加慢,因为需要遍历找到到最后一个指向为null的节点
插入和删除快 因为可以直接改变下一个节点的指向
不保证线程安全
不支持高效的随机元素访问
RandomAccess未实现,优先选择iterator遍历(foreach遍历底层也是通过iterator实现的,),大size的数据,千万不要使用普通for循
双向链表: 包含两个指针,一个prev指向前一个节点,一个next指向后一个节点。
双向循环链表: 最后一个节点的 next 指向head,而 head 的prev指向最后一个节点,构成一个环。
Set
HashSet
不能重复,无序
是数组+链表
HashSet底层使用了哈希表来支持的,特点:存储快
自定义数据类型 ,equals()和hashCode()
本质就是实现了一个HashMap线程是不安全的
hashset在add的时候是实现了一个hashmap,然后hashmap在put的时候就是不安全的,多线程的情况下数据会被覆盖,还有一个++size的操作,不是原子性的
LinkedHashSet
底层采用链表加哈希表,元素有序且唯一,链表保证元素有序,哈希表保证元素唯一,线程不安全,效率高
实现FIFO
TreeSet
根据源码可知,TreeSet的底层使用到TreeMap
TreeSet中的元素是有序且不重复的,因为TreeMap中的key是有序且不重复的
Map
HashMap
HashMap 数据结构为 *数组+链表*,其中:链表的节点存储的是一个 Entry 对象,每个Entry 对象存储四个属性(hash,key,value,next)
put的扩容机制
默认数组容器大小为16,加载因子为0.75 阈值为16*0.75=12
通过自己的hash算法算出当前key的hasha值
通过计算hash值去调用indexfor方法计算当前对象应该存储的数组的几号位置
判断size是否达到了当前的阈值,没有继续,如果达到的话扩容,扩容为原来的2倍
size 是当前数组中entry的数量,不是数组的长度
hash将当前对应的key,value封装成一个entry ,去查找当前数位置有没有元素,没有方上面,有的话遍历如果某个节点的key的当前的key equals为true则返回value,当前的value补上去,如果没有,西就是先来的往后退
HashMap 使用 “懒扩容” ,只会在 PUT 的时候才进行判断,然后进行扩容
- 将数组长度扩容为原来的2 倍
- 将原来数组中的元素进行重新放到新数组中
即当链表超过8时,链表就转换为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能,其中会用到红黑树的插入、删除、查找等算法。
不是安全线程解决方法如下
Map m = Collections.synchronizedMap(new HashMap(...));