集合
Java集合框架:基础知识,Collection,Map
基础知识:
- 数据物理结构[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5WXn3jYX-1614087087207)(C:\Users\fallrain\AppData\Roaming\Typora\typora-user-images\image-20210223201004900.png)]
- 数据逻辑结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8mIwmqc-1614087087210)(C:\Users\fallrain\AppData\Roaming\Typora\typora-user-images\image-20210223201228120.png)] - 线程安全
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RmfMXO5X-1614087087212)(C:\Users\fallrain\AppData\Roaming\Typora\typora-user-images\image-20210223201318177.png)]
Collection:
- List
- ArrayList
- 数据结构:动态数组+动态扩容,添加元素时容量不够,新建一个数组,长度为原数组的长度*扩容因子(1.5),新元素放入新数组,并将新数组赋值给集合,原数组丢弃
- Vector
- LinkedList
- 数据结构:链表+维护内部的Node,
- 元素以Node节点的item属性存在,同时维护next和prevent记录前驱后继指针。双端队列实现了Deque接口,支持从首部和尾部存取元素
- CopyOnWriteArrayList
- 数据结构:ArrayList+Array,
- 写时加锁复制,Reentrant Lock保证线程安全,修改数组之前先将数组拷贝一份,操作新数组,并赋值给Array,抛弃旧数组;读操作无锁。
- ArrayList
- Set
- HashSet
- 底层使用HashMap存储数据,用key存储元素
- 元素不重复,key不能重复
- 元素无序,key 无序
- 元素允许一个null值,key允许有一个null值
- 非线程安全,没有get方法
- 虚拟对象PRESENT,存map的时候,value固定为此值
- 底层使用HashMap存储数据,用key存储元素
- LInkedHashSet
- TreeSet
- CopyOnwriteArraySet
- ConcurrentSkipLIstSet
- HashSet
- Queue
- BlockingQueue
Map:
-
HashMap
-
数据结构:链表+数组
-
JDK8开始链表高度达到8,数组长度超过64时,链表转为红黑树:构造红黑树比构造链表难,在链表节点不多的时候,从整体性能来看,数组+链表+红黑树的结构可能不一定比数组+链表的结构性能高
频繁的扩容会造成底部红黑树不断进行拆分和重组,非常耗时,因此也就是链表长度比较长的时候转变为红黑树才会显著提高效率
-
元素以内部类Node节点存在
-
-
元素存储
- 计算key的hash值,二次hash然后对数组长度取模,对应到数组下标
- 如果没有产生hash冲突,则直接创建Node存入数组
- 如果产生hash冲突,先进行equeal比较,相同则取代该元素,不同,则判断链表高度插入链表,链表高度达到8,并且数组长度到64,转变为红黑树,长度低于6则将红黑树转换为链表
-
扩容
- 元素个数达到阈值threshold, 扩容2倍, 新建数组
- 旧数组的数据到新数组, 遍历旧数组, 重新计算每个元素的存储位置, 逐个转移数据(jdk7头插法, jdk8尾插法)
- 新数组引用到全局变量table
- 重新设置阈值threshold
-
初始容量 可以入参指定,官方要求输入2的N次方, 如果不是则取最近的2的N次方
-
负载因子loadFactor 扩容时的阈值:默认0.75
-
迭代器:fail-fast
-
-
Hashtable
- 数据结构同HashMap(无红黑树), 操作也一致
- synchronized保证线程安全
-
ConcurrentHashMap
- JDK7
- 数据结构: ReentrantLock+Segment+HashEntry, 一个Segment中包含一个HashEntry数组, 每个数组又是一个链表结构
- 元素查询: 第一次定位到Segment, 第二次定位到元素链表的头部
- 锁:Segment分段锁, Segment继承了ReentrantLock, 锁定操作的Segment, 其他的Segment不受影响, 并发度为segment的个数, 数组扩容不会影响其他的segment
- JDK8
- 数据结构: synchronized+CAS+Node+红黑树 Node的val和next都用volatile修饰,保证可见性
- 查找, 替换, 赋值操作都使用CAS
- 锁: 锁链表的head节点,不影响其他元素的读写,锁粒度更细, 效率更高, 扩容时, 阻塞所有的读写操作
- 并发扩容
- 一个线程发起扩容的时候,就会荣国cas设置sizeCtl属性(volatile修饰) 告知其他线程扩容状态变更,创建一个两倍容量的新数组nextTable, 单线程完成
- 扩容时会判断sizeCtl属性, 如果超过阈值就要扩容
- ForwardingNode节点
- JDK7
-
TreeMap
- 红黑树实现
-
LinkedHashMap
- 继承自HashMap
- 顺序
- accessOrder为false 插入顺序保存
- accessOrder为true 访问顺序保存,访问会导致顺序变动,最近访问的元素在最后面,利用这个特性可以实现LRU
- 双向链表 元素直接有指针双向链表
-
Properties
- 以key- value的键值对的形式进行存储, key值不能重复
- xml和properties文件相互转化