目前梳理学习计划有变动,mybatis源码学习暂且搁置,等下一阶段再去进行学习,原因是目前能力有限,精力有限,mybatis学习过于消耗时间。目前规划是优先完成lottery这个系统,做这个系统时,主要考虑点包含以下几个方面:
(1)项目的功能点是否明确?—— 细化到数据库表,接口,消息组件的消息传递
(2)项目的拓展性该如何保障——性能扩展性和功能扩展性
(3)项目可靠性该如何保证——如何避免产生更多的bug
中间有如果有完备的技术方案会进行分析。
本次主要针对Collection进行分析学习,主要关注点有三个:
(1)各个集合的存储结构
(2)各个集合的扩容机制
(3)能在项目中做哪些事情
一、集合的概述
集合是一种容器,一种存储的容器,与数组类似,却又不同于数组,主要区别点以下几点:
(1)集合长度不固定,而数组一旦定义,长度和存储对象都会固定;
(2)数组中可以存储引用对象和基本对象,而集合中只能存储引用对象,那如果在集合中插入类型20的对象呢?集合这块会自动装箱,将基础数据类型转换为引用数据类型。
二、Collection架构
Collection为接口,list(接口,有序,有下标)和set(接口,无序,无下标)继承Collection;
ArrayList,LinkedList,Victor(线程安全,存储结构为数组—相当于对数组结构进行封装)继承自List;HashSet和TreeSet继承自Set。——底层实现都是具体的方法。
三、list接口与实现类
list:有序,有下标,元素可以重复
1、ArrayList:数组结构实现的,查询快,增删慢,运行效率快,线程不安全。vector也是数组实现,但安全,运行慢。
容量的拖延机制:(建议看源码)—— 数组的不断加长
(1)刚开始new,长度为0
(2)首次添加,长度为10
(3)old+old>>1,之后看得出的长度和插入的数组之后的长度比对,如果new较大,则为new,反之则为另外一个
array扩充的主方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
2、LinkedList:链表(双向)增删快,查询慢
每次的节点(数据)添加,只需要建立上个节点与下个节点之间的关系(指明所联系的上下节点即可)
以上可以看出array必须开辟连续的空间(数组的不断拖延),linked则不需要去进行开辟。
linked扩充的主方法
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
针对具体的业务,arraylist和linkedlist没有操作空间,只需在使用时标注泛型——进行校验即可。
四、set接口与实现类
set存储方式,无序,无下标,元素不可重复。set的主要实现有两种,hashset和treeset。
1、HashSet:基于HashCode计算元素存储位置,存储的结构是哈希表,即数组+链表+红黑树
存储过程:
(1)根据HashCode计算保存位置,如果位置为空则进行直接保存,如果位置不为空则进行下一步;
(2)执行equals方法,如果equals为true则进行不保存,如果equals为false进行保存。
为什么会有这种存储规则?因为集合只存储引用对象,这些都是Object类天然具备的方法。
业务中怎么使用?重写hashcode和equals进行插入筛选。
HashSet的添加和拓延都遵循HashMap的key,HashMap中具体将拓展机制。
2、TreeSet:基于红黑树进行存储,元素不重复的保障机制是比较器,即Comparable或者内部实现类进行操作,返回一个int,是0则相等,正数则大于,负数则小于。机制也参照TreeMap中的key.
五、map接口与实现类
map接口的实现类有HashMap和TreeMap。存储的是键值对,双列集合,键是无序,无下标,不允许重复——引入一个场景:当遍历key获取value时,建议使用entrySet实现。
1、HashMap:线程不安全——线程不安全的本质原因是什么?哈希冲突吗,下来确认下。顾名思义,存储结构是哈希表,即数组+链表+红黑树,当然,这些都是针对key值而言——value与key的链接也是使用节点形式,类似于linkedList.
数据能否插入的前提是HashCode和equals方法的重写规则。
拓延机制:(默认初始容量16,拓展系数0.75)
(1)构造时为0
(2)首次添加resize()为16 1<<4
(3)当达到拓展系数,扩展数据结构为原来的两倍:16 32 64 128 256
什么时候链表会转换为红黑树?数组长度大于64(产生64个不同的HashCode值,链表长度大于8,链表结构转换为红黑树)—— 什么时候又回到链表呢?红黑树的树深从8到6
2、HashTable:线程安全,运行速度慢
3、TreeMap:存储结构也是基于红黑树,对key进行自动排序,需要定义比较器。