文章目录
集合概览
- Collection接口:单列集合,用来存储一个一个的对象
- List接口:存储有序的、可重复的数据。->ArrayList、LinkedList、Vector
- Set接口:存储无序的、不可重复的数据 ->HashSet、LinkedHashSet、TreeSet - Map接口:双列集合,用来存储一对(key - value)一对的数据->HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
tips:List接口和Set接口属于Collection的子接口,Map不属于
List
List概览
- List接口:存储有序 可重复 的数据
- ArrayList:作为List接口的主要实现类;线程不安全 的,效率高;底层使用Object数组存储
- LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用 双向链表 存储
- Vector:作为List接口的古老实现类;线程安全 的,效率低;底层使用Object[]数组存储
ArrayList的源码分析(掌握)
jdk1.7时的ArrayList
1.空参初始化 -> ArrayList list = new ArrayList();->这时底层初始化了一个长度为10的Object[]数组elementData
2.添加数据 -> list.add(123) -> elementData[0] = new Integer(123);
3.扩容->如果某次的添加导致底层elementData数组容量不够,则扩容->
默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
jdk1.8时的ArrayList的变化
1.空参初始化,底层Object[]数组初始化为{},并没有创建长度为10的数组,第一次调用add()时,底层才创建了长度10的数组,并将数据添加到elementData[0]
2.添加和扩容与jdk1.7无异
小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,好处为延迟了数组的创建,节省内存。
LinkedList的源码分析(了解)
ArrayList底层存储数据的是Object[]数组,而LinkedList底层存储数据的是双向链表
初始化:LinkedList list = new LinkedList(); ->内部声明了Node类型的first和last属性,默认值为null
添加:list.add(123);->将123封装到Node中,创建了Node对象。
底层Node的定义
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
Vector的源码分析(了解)
jdk7和jdk8中通过*Vector()*构造器创建对象时,底层都创建了长度为10的数组。
-
在扩容方面,默认扩容为原来的数组长度的2倍。
Set
Set概览
- Set接口:存储无序 不可重复 的数据
- HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
- LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
- TreeSet:可以按照添加对象的指定属性,进行排序
HashSet的源码分析(掌握)
HashSet的底层结构图
添加元素的过程:
1.我们向HashSet中添加元素a,首先调用元素a所在类的 hashCode() 方法,计算元素a的哈希值
2.此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为索引位置)
3.判断数组此位置上是否已经有元素:
情况①:如果此位置上没有其他元素,则元素a添加成功。
情况②:如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值,如果hash值不相同,则元素a添加成功。
情况③:如果hash值相同,进而需要调用元素a所在类的equals()方法: equals()返回true,元素a添加失败,equals()返回false,则元素a添加成功
- HashSet的底层结构图(数组加链表)
tips: 其实这个图也是HashMap的底层结构图,为什么他们两个底层结构一样呢?因为其实HashSet底层就是一个HashMap,通过下图的代码也可以看到
创建了一个HashSet其实就是底层创建了一个HashMap,想了解HashMap可往后看HashMap的源码分析
HashSet jdk1.7与1.8的不同
经过比较可以添加元素时,如果添加位置上已经有了元素存在的话:
jdk1.7的处理->需要添加元素放到数组中,指向原来的元素(可理解为头插法)
jdk 8的处理->原来的元素在数组中,指向需要添加元素(可理解为尾插法)
总结:七上八下
Map
写博客也太费时了把。。先休息一会儿。。