ArrayList
ArrayList实现于List、RandomAccess接口。可以插入空数据,也支持随机访问。其中最重要的两个属性分别是:elementData数组,以及size大小。。默认初始化容量为10,每次扩容会扩容1.5倍(新容量=旧容量+旧容量>>1)。有序、非线程安全的。
执行add(E)方法:
首先记录对该列表进行结构修改的次数
然后执行添加元素,默认添加到末尾
判断数组的容量是否满了,如果是就先进行扩容
将元素添加到指定位置,修改size大小
执行add(index,e)方法,添加元素到指定位置:
check下标是否越界,并记录列表结构修改次数
判断数组是否需要扩容
通过System.arraycopy方法复制指定的元素向后移动
将添加的元素赋值给指定的下标,修改size大小
扩容方法grow():
主要通过旧的容量+旧的容量,然后右位移1位来计算新的容量
通过容量创建一个新的数组,进行数组复制
Vector
底层使用数组实现,扩容方式与List不同,如果初始化Vector时没有指定容量增量,那么会默认扩容2倍(新容量=旧容量+旧容量),如果指定了容量增量,那么扩容的容量就是(新容量=旧容量+容量增量),使用synchronized包装了类的方法,所以是线程安全的,并且有序
执行add(E e)方法:
判断是否需要扩容
赋值元素到指定的下标
修改容器大小
LinkedList
采用双向链表实现,get指定索引的值会先对链表的大小进行右位移1,来判断获取的索引值在链表的上半部分还是下半部分,如果是上半部分会从头部节点开始遍历查找,如果是下半部分会从尾部节点开始遍历查找,有序、非线程安全。
执行add(E e)方法:
默认添加到链表的最后面,先取出lastNode的一个临时变量。
将要添加的元素包装成一个newNode节点,将newNode节点的前置节点设置为当前链表最后一个节点
将newNode设置为新的last节点
判断lastNode是否为空,如果为空,那么此时添加的是链表的第一个节点,那么直接设置firstNode等于newNode。如果不是就将newNode链接到lastNode后边
修改链表大小及结构修改次数
执行get(int index)方法
先判断要获取的索引是否超出链表大小
通过size左位移一位来判断index是在链表上半部分还是下半部分
如果在上半部分则通过头结点开始遍历查找
如果在下半部分则通过尾结点开始遍历查找
HashSet如果保证数据不重复?
HashSet底层结构是一个HashMap,HashSet将值放在HashMap的键中,如果HashMap的键相同时会发生覆盖,因为HashSet的值不会重复。HashMap检查Key是否相同会通过equles方法,并通过比较hash值判断是否重复。
TreeSet
底层使用NavigableMap实现,所有添加到set中的元素最终都会添加到map的key中,value用一个final的object对象填充。有序不重复,非线程安全
HashMap
HashMap初始容量为16的Node数组,数组内的链表容量大于8时会自动转换为红黑树,只有当这个数大于2并值至少有8个才能满足树的假设,当这个值缩小到6的时候就会转换为链表。
当链表长度大于阈值(默认为8)时,会首先调用treefyBin()方法。这个方法会根据HashMap数组来决定是否转换为红黑树