集合所属的类在java.util包下
集合可分为两种collection单列存储,map双列集合
一、collection(单列集合)
list:存储有序的、数据可重复
ArrayList、LinkedList、Vector三种实现类
ArraryList:LIst的主要实现类,线程不安全、效率高底层使用Object[ ]存储,在JDK7中初始创建时长度为10,在JDK8开始创建时先初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};;第一次创建时才是长度为10,扩容是1.5倍
初始化
创建
扩容
LinkedList:底层用双向链表存储,插入、删除效率高
Vctor:线程安全、效率低,底层同用Object[ ]存储,每次扩容为原来的2倍(现在很少采用)
-
set:存储无序的、不可重复的数据,没有额外定义的新方法,只用collection中的方法
-
HashSet:存储无序的,不可重复的数据,作为set的主要实现类,线程不安全,可以存储null值,JDK7底层数组+链表实现,数组初始长度为16,同一位置链表插入使用头插法,JDK8使用数组+链表+红黑树实现,添加时指定长度为16;同一位置链表使用尾插法
- 向HashSet添加元素a,首先调用元素a所在的类的HashCode方法,计算a的哈希值,此哈希值接着通过某种计算方法,计算出HashSet底层数组的存放位置(即索引位置),判断此位置上是否有元素,如果没有元素,直接放入,如果有元素进行比较,先用哈希值比较, 如果哈希值不同放入后面(采用JDK8尾插说法),如果哈希值相同,在调用equals()方法比较,返回true添加失败,返回false,可以放入,在此位置中已经有元素的时候用链表串起来放在数组的一个位置
- 基于以上的只是,我们可以知道在向set中添加数据时,所在的类一定要重写HashCode(),equals()方法,重写这两个方法尽可能保持一致性,相等的对象必须具有相等的散列码
- 重写技巧,对象中用作比较的属性,都应用来计算hashcode值(快捷键生成)
-
LinkedHashSet:作为HashSet的子类,遍历内部数据时,可以按照添加的顺序遍历(双向链表,再添加时维护了两个引用,记录此数据的前一个和后一个)
-
TreeSet:(放入类型相同的数据)可以按照添加的对象的指定属性,进行排序(自然排序是实现Comparable接口,定制排序实现comparator接口用重写compare()方法定制排序方式即规定用什么排序,但是内部还是调用compareTo(放入参数)比较)
注意:
1.无序性不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数组的哈希值存储
2.不可重复性:保证添加的元素按照equals(),判断时不是返回true,即同一个元素只能添加一个
3.对于频繁遍历操作LinkedHashSet效率高于HashSet
二、Map双列集合
map:双列集合,存储用<key,value>的键值对数据。
HashMap:Map主要实现类,线程不安全,效率高,可存储null值得key和value
LinkedHashMap:保证遍历map元素时,可以按添加顺序遍历(添加了一堆指针维护)(对于频繁遍历操作,此类效率高于HashMap)在JDK7以前底层是数组+链表实现,JDK8采用数组+链表+红黑树存储
TreeMap:保证按照key-value对进行排序,是先排序遍历,底层采用红黑树
HashTable:作为古老实现类,线程安全,,效率低,不能存储null得key和value
Properties:常用来处理配置文件,key和value都是String类型
Map的结构
- Map的key:无序的、不可重复的,使用set存key(所在类重写equals()、hashcode()方法)
- Map的value:无序的、可重复的,使用collection存储value
- 一个键值对:key-value构成了一个Entry对象
- Map的entry:无序的、不可重复的,使用set存储
经典面试题
HashMap底层实现原理
先以JDK7为例说明
- HashMap map = new HashMap();在实例化以后,底层创建了一个长度为16的一维数组Entry[ ] table
- map.put(key,value):先调用key所在类的hashcode()计算key的哈希值,此哈希值经过某种算法运算后,得到在Entry中的存放位置
- 如果此为位置上数据为空,(key,value)添加成功;
- 如果此位置的数据不为空,意味着这个位置已经存在了一个/多个数据(链表形式),比较key和已经存在的一个或多个数据的哈希值,
- 如果key与已存在的所有数据都不同,则添加成功
- 如果key的哈希值与某个Entry相同,继续比较,调用key所在的equals()方法
- 如果为false,添加成功
- 如果true,使用value替代之前Entry中的value
添加过程中,涉及到扩容,默认以2倍扩容复制到原有数组
JDK8相较于JDK7的不同方面
- new HashMap():底层没有创建长度为16的数组,
- JDK8底层数组是Node[ ],而不是Entry[ ],
- 首次调用put(),方法,底层创建一个长度为16的数组
- JDK7 底层结构:数组+链表,JDK8底层:数组+链表+红黑树,当数组的某个索引位置上的元素以链表的形式存在的的数据个数>8并且当前数组的长度>64时,此时索引位置上的所有数据改用红黑树存储
HashMap和Hashtable的异同
- 相同点,都作为Map的实现类,双列存储<key,value> 都要求key唯一
- 不同点 HashMap线程不安全,效率高,可以存储null值作为key和value, Hashtable线程安全,效率低,不能存储null值作为key或value
总结
抓住主要的,对于集合这一块可以进行对比记忆,多看看底层源码,加深记忆,不知道为什么这目录只生成这么多,还改了一下还是不行