Java集合
Java的集合类主要由Collection接口和Map接口派生而来,其中Collection接口由两个常用的子接口,即List接口和Set接口,所以常说的Java集合框架由三大类接口构成(Map接口、List接口和Set接口)
List接口
- List的实现类有Vector、ArrayList、LinkedList、Stack等
- Stack类内部是栈结构。是Vector类的子类
- Vector是线程安全的
- ArrayList是非线程安全的,ArrayList内部使用数组存储元素
- LinkedList内部使用双向链表存储元素,
- 因此:ArrayList集合随机访问效率高于LinkedList集合,而LinkedList集合在插入元素,删除元素使效率高于ArrayList
Set接口
- 实现类:HashSet类和TreeSet类
Map接口
- 实现类:HashMap类和Hashtable类等
Collection
Collectio继承了Iterable接口,
Iterable
实现了Iterable接口的类可以通过实现iterator()方法来返回一个迭代器对象,从而使其可以使用for-each循环语法来遍历集合中的元素
在迭代的过程中不能改变结构
Queue接口
- 继承自Collection接口的子接口
- Queue接口不容许插入null元素,也不容许重复的元素
- 实现类:LinkedList、ArrayDeque
Deque接口
- 继承自Queue接口
- 双向操作
- 队列的特点:先进先出
- 栈特性
- 实现类:ArrayDeque、LinkedList
List接口
List接口继承自Collection接口
- 是有序的集合
- List接口的实现类:ArrayList、LinkedList、stack、Vector等
ArrayList
- 对于ArrayList而言,它实现了List接口,底层使用数组保存所有元素
- ArrayList提供了三种方式的构造器
LinkedList
LinkedList类是List接口的链接列表实现类,它支持实现所有List接口可选的列表的操作,并且容许元素值是如何数据,包括null
LinkedList实现了Deque接口,既能将LinkedList当做双端队列使用,
Vector
- 实现类List接口
- 动态数组:底层是一个数组
- 线程安全
- 支持随机访问
- 可以包含重复元素
- 可以插入null元素
stack
- stack类是一种后进先出的数据结构,实现类栈的特点‘
- 后进先出
- 继承自Vector
Set接口
- Set接口是Collection接口的另外一个常用子接口
- 无顺序
- 不重复
- 不容许使用索引
- 非同步
HashSet
- 元素唯一
- 无序性
- 基于哈希表
- 非同步
- 容许null
TreeSet
- 实现了Set接口的有序集合,它使用红黑树
- 元素安装自然排序或者指定的构造器
- 元素唯一性
- null元素的处理:不容许null
- 插入、删除、查找:基于红黑树
- 迭代器顺序
Map接口
- 键值对应:
- 无序性
- 容许空键值
- 非同步
HashMap
- 容许nul键和null值
构造方法
- HashMap()无参构造函数:默认容量初始化时16,默认的加载因子是0.75
- HashMap(intinitialCapacity)可以对容量进行设置,健壮因子默认值是0.75,调用的是下面的有参构造函数
- HashMap(int initialCapacity,float loadFactor)可以指定容量和加载因子,容量不可以小于0,也不可以无限大,加载因子也不能为0,也不能比0小
- HashMap(Map map)创建一个新的HashMap,加载因子是默认值0.75.然后通过putMapEnries()将map的值存储到新的HashMap中
- HashMap底层原理:底层是数组,称为哈系桶【jdk7是数组+链表、、、jdk8是数组+链表+红黑树】
Hashtable
- 线程安全
- 键值不容许为null
- 解决哈希冲突
- 动态扩容
Queue接口
- 继承Collection接口
- Queue接口不容许null
ArrayDeque是Queue的实现类
- 继承自AbstractCollection
- 实现Queue接口
- 底层是数组存储
LinkedList也是Queue的实现类
- 继承AbstractSequentialList抽象类
- 实现List、Deque、Cloneable接口
- 底层是一个链表
Deque是非线程安全的
List接口
- 可以存储一组不唯一、无序的对象
- List接口继承自Collection接口
- 是有序集合
- 可以通过索引访问List接口中的元素
- 实现类:ArrayList、LinkedList、Stack、Vector
ArrayList是List的实现类
-
ArrayList继承自AbstractList抽象类
-
ArrayList实现了List、Cloneable接口
-
底层的存储使用的是数组
-
添加元素是先判断数组是否越界,如果越界使用grow()进行扩容
-
有三种构造方法
-
非线程安全
-
删除元素后,因为底层是数组,所以长度会变化
-
List list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); list.remove(0); System.out.println(list.get(0));//b System.out.println(list.size());//2
-
LinkedList是List的实现类
- 继承自AbstractSequentialList抽象类
- 实现了List、Deque、Cloneable接口
- 容许元素值是如何,可以是null
- 可以当做双端队列使用
- 底层是通过双向链表实现的
- 非线程安全
Stack是List的实现类,但是他不直接实现List,而是通过继承Vector实现List接口
- 后进先出
- 继承自Vector
- 线程安全
- 底层是数组
- 可以包含null
- 支持随机访问
Vector也是List的实现类
- 继承自AbstractList抽象类
- 实现了List、Cloneable接口
- 默认构造的容量为10
- 线程安全
- 可以包含重复元素
- 可以插入null元素
Set接口
- set接口是Collection接口的另一个常用子接口
- 存储唯一
- 无序对象
- 不容许重复元素
- 不容许使用索引
- 非同步(非线程安全)
HashSet是Set的实现类
- 继承自AbstractSet抽象类
- 实现了Set、Cloneable接口
- 基于哈希表实现
- 非同步
- 容许null
- 元素唯一
- 无序性
- 默认加载因子0.75
TreeSet实现Set
- 基于红黑树实现的,具有排序功能
- TreeSet可以按照元素的自然排序进行排序,也可以提供比较器来指定排序规则
- 元素唯一性
- null元素的处理,不容许null
LinkedHashSet实现Set接口
- 元素唯一
- 保证元素插入顺序
- 基于哈希表和链表实现的
- 容许null
- 迭代器顺序,按照插入顺序进行遍历
Map接口
- 键唯一、值可重复
- 无序性
- 容许空键值
- 非同步
HashMap实现Map接口
- 继承自AbstractMap抽象类
- 实现Map、Clonable接口
- 默认初始容量必须是2的次幂(16)
- 、构造函数中未指定时使用的负载系数为0.75
- 链表的长度超过8,转为树
- 如果树的长度超过64,则对数组进行扩容
- 负载因子:判断是否需要扩容,默认值为0.75
- 阈值:当HashMap的大小超过一定阈值时,会触发扩容操作
- HashMap底层是数组
- Jdk7==数组+链表
- Jdk8===数组+链表+红黑树
put的过程
- 根据key计算hash值,在put的时候判断数组是否存在,如果不存在则用resize方法创建默认长度为16的数组
- 确定要存入的Node在数组中的位置,根据hash值与数组最大索引进行按位与运行得到索引的位置
- 判断该位置是否有元素,如果没有直接创建一个Node存入,如果有元素,判断key是否相同,如果相同则覆盖,并且将原来的值直接返回,如果key不相同,在原Node的基础上添加新的Node,判断该位置是否是红黑树
- 如果是红黑树,将Node存入红黑树
- 如果是链表,遍历链表,找到最后一位,将Node存入
- 将Node存入链表之后,判断链表的结构是否要调整,判断链表长度是否超过8,如果超过8需要将链表转为红黑树,这里还有一个条件,如果数组容量小于64,不转换红黑树,而是进行数组扩容,当数组的容量大于64的时候,再将链表转为红黑树
- 存完之后,在判断数组是否进行扩容,根据负载因子来判断
入,如果有元素,判断key是否相同,如果相同则覆盖,并且将原来的值直接返回,如果key不相同,在原Node的基础上添加新的Node,判断该位置是否是红黑树
4. 如果是红黑树,将Node存入红黑树
5. 如果是链表,遍历链表,找到最后一位,将Node存入
6. 将Node存入链表之后,判断链表的结构是否要调整,判断链表长度是否超过8,如果超过8需要将链表转为红黑树,这里还有一个条件,如果数组容量小于64,不转换红黑树,而是进行数组扩容,当数组的容量大于64的时候,再将链表转为红黑树
7. 存完之后,在判断数组是否进行扩容,根据负载因子来判断