重温javase集合
前言:
1、为什么要有集合?
数组长度需要在初始化时确定大小,数据结构单一、因此集合出现了
2、数组和集合的区别
区别一:数组既可以存储基本数据类型,又可以存储引用类型,集合只能存储引用类型
区别二:数组在初始化的时候就需要确认大小,集合有默认初始大小和扩容机制
区别三:集合类有丰富的封装方法
UML图#
粗边框的是常用的的类,虚线边框是接口
集合的两大接口#
Collection 接口#
常用方法:
方法名 | 说明 | 返回类型 | 参数 |
---|---|---|---|
add | 添加元素到末尾 | boolean | 添加的元素对象 |
addAll | 合并另一个Collection | boolean | 实现了Collection的集合 |
contains | 检查是否包含某个元素 | boolean | 元素对象 |
containsAll | 检查是否包含集合 | boolean | 实现了Collection的集合 |
isEmpty | 集合是否为空 | boolean | 无参 |
remove | 移除元素 | boolean | 元素对象 |
removeAll | 移除集合中有另一个集合的元素 | boolean | 实现了Collection的集合 |
size | 返回集合大小 | int | 无参 |
toArray | 转换成数组 | [ ] | 无参 |
遍历方式:
- 迭代器 Iterator (需要删除元素时推荐用这个)
- forEach
实现接口:List、Set、Queue
List常用方法#
方法名 | 说明 | 返回类型 | 参数 |
---|---|---|---|
add(String item, int index) | 添加元素到指定位置 | void | 索引,元素 |
addAll(int index, Collection<? extends E> c) | 添加集合到指定位置 | boolean | 索引,集合 |
get(int index) | 获取值 | 元素 | 索引 |
indexOf(Object o) | 判断List中是否有这个元素,有返回索引,无返回-1 | int | 元素 |
listIterator() | 返回List迭代器 | ListIterator | 无参 |
listIterator(int index) | 返回List迭代器,光标移动到参数索引处 | ListIterator | 索引 |
remove(int index) | 移除List元素 | 元素 | 索引 |
set(int index, E element) | 替换元素 | 元素 | 索引,元素 |
subList(int fromIndex, int toIndex) | 分割List | List | 开始索引,结束索引 |
retainAll(Collection<?> c) | 仅保留包含在指定集合中的此集合中的元素 | boolean | Collection |
lastIndexOf(Object o) | 返回此列表中指定元素的最后一个发生的索引,如果没有返回-1 | int | 元素 |
List特有遍历方式:
- get
- List迭代器
List常用实现类#
- ArrayList
特点:查找速度快,删除添加元素慢,因为底层使用数组(地址+偏移量就可定位到元素,实际上是对引用地址的访问),索引位置变化,大于索引的都要往前移一个,线程不安全 - LinkedList
特点:查找速度慢,删除添加元素速度快,因为底层使用链表,需要从头或者从尾开始一个一个查找,删除添加只需要改变上一个节点的引用即可,线程不安全 - Vector
特点:和ArrayList一样,方法中加入了同步代码块,现在被弃用,线程安全 - Stack
特点:Vertor的子类,现在被弃用,被Deque队列代替 - CopyOnWriteArrayList
特点:写操作加锁,读操作不加锁,适合读多的场景,原理是写操作时会复制一份副本,写的动作在副本中完成,然后将副本赋值回去,线程安全
对应的非并发容器:ArrayList
Set常用方法#
方法名 | 说明 | 返回类型 | 参数 |
---|---|---|---|
retainAll(Collection<?> c) | 仅保留包含在指定集合中的此集合中的元素 | boolean | Collection |
... | ... | ... | ... |
Set特点:
无序,存储元素不可重复,元素必须重写hashCode和equlas方法,判断元素是否重复的原理:
调用hashCode() 没有相同的就放入,有相同的再调用equlas()判断
Set常用实现类#
-
HashSet
特点:无序、元素完全使用HashMap的key来存储,线程不安全 -
TreeSet
特点:有序、使用红黑树为元素排序,默认自然排序:就是元素自身具备的比较性实现了Comparable接口的compareTo()方法。更改默认排序有两种方式:- 构造函数中传入Comparator
- 元素实现Comparable
线程不安全
-
LinkedHashSet
特点:有序、HashSet的子类,使用链表来存储插入的顺序,value是LinkedHashMap的key。需要遍历完全部元素的情况下比HashSet效率高。线程不安全 -
CopyOnWriteArraySet
特点:写操作线程安全
对应的非并发容器:HashSet -
ConcurrentSkipListSet
特点:写操作线程安全
对应的非并发容器:TreeSet
Queue常用方法#
方法名 | 说明 | 返回类型 | 参数 |
---|---|---|---|
add(E e) | 添加元素到队列,超过容量大小会报异常 | boolean | 元素 |
offer(E e) | 添加元素到队列,超过容量大小返回false | boolean | 元素 |
element() | 检索队列头部元素,空队列使用会报异常 | 元素 | 无参 |
peek() | 检索队列头部元素,空队列使用返回null | 元素 | 无参 |
remove() | 检索和删除此队列的头,空队列使用会报异常 | 元素 | 无参 |
poll() | 检索和删除此队列头部元素,空队列使用返回null | 元素 | 无参 |
Queue特点:#
队列不允许插入null元素,而LinkedList可以
Queue常用实现接口:#
BlockingDeque (阻塞双端队列), BlockingQueue(阻塞队列) , Deque (双端队列)
阻塞队列:#
队列一般都有着两个阻塞操作,即插入与取出。
当队列满时,会阻塞元素的插入,直到队列有空闲时停止阻塞,新元素才可以继续插入。
当队列为空时,移除元素的线程会一直被阻塞等待,直到队列中有元素时才可以继续取出。
除拥有普通队列的方法之外,阻塞队列提供了另外4个常用的方法:
put(E e):向队尾插入元素,若队列已满,则被阻塞等待,直到有空闲才继续插入。
take():从队首取出元素,若队列为空,则被阻塞等待,直到有元素才继续取出。
offer(E e,long timeout, TimeUnit unit):向队尾插入元素,若队列已满,则计时等待,当时间期限达到时,若队列还是满的,则返回false;若等待在期限内,队列空闲,则插入成功,返回true;
poll(long timeout, TimeUnit unit):从队首取出元素,如果队列空,则计时等待,当时间期限达到时,若队列还是空的,则返回null;若等待在期限内,队列中有元素,否则返回取得的元素;
Queue常用实现类#
- ArrayDeque
特点:是双端队列的数组实现类,不允许null值,非线程安全 - PriorityQueue
特点:可以排序的队列,区别在于PriorityQueue会根据自然顺序或者是根据构造队列时提供的Comparator的排序规则进行排序,存储元素一定要是可比较的元素,否则需要指定其比较器,是一种无界的,线程不安全(没有加锁操作)的队列 - ConcurrentLinkedQueue
特点:线程安全 - LinkedBlockingQueue
特点:阻塞队列、基于链表实现的可阻塞的FIFO队列 - ArrayBlockingQueue
特点:阻塞队列、基于数组实现的可阻塞的FIFO队列 - PriorityBlockingQueue
特点:阻塞队列、按优先级排序的队列
Map接口#
常用方法:
方法名 | 说明 | 返回类型 | 参数 |
---|---|---|---|
put | 添加 | void | key,value |
putAll | 合并另一个Map | void | 实现了Map的集合 |
containsKey | 是否包含key | boolean | key |
containsValue | 是否包含这个值 | boolean | value |
keySet | 返回Map所有的key | Set | 无参 |
values | 返回Map所有的value | Collection | 无参 |
entrySet | 返回key value | Entry | 无参 |
remove | 删除 | value | key |
remove | 如果key和value相匹配则删除 | boolean | key,value |
size | 返回有多少个元素 | int | 无参 |
clear | 清除 | void | 无参 |
get(Object key) | 根据key获取value | value | key |
getOrDefault(Object key, V defaultValue) | 根据key获取value,如果没有这个key返回默认值 | default or value | key,default |
遍历方式:
- entrySet (最常用 性能好)
- values
- keySet
- Iterator
- forEach
Map特点#
双列数据结构,key、value,通过散列算法来找value
Map常用实现类#
-
HashMap
特点:数据结构为散列表+链表/红黑树(一种自平衡的树)、如果散列算法不成功,会导致一个槽里面会有多个值,如果这个值超过8个,会由链表转成红黑树,反之少于8个会由红黑树转成链表。线程不安全 -
TreeMap
特点:有序,TreeSet使用的TreeMap的key。线程不安全 -
LinkedHashMap
特点:是HashMap的子类,有序,LinkedHashSet使用的LinkedHashMap的key。线程不安全
-
HashTable
特点:和HashMap类似,其方法里面加了很多同步代码块,不能使用null作为key。
现在已经为抛弃,线程安全。ConcurrentHashMap现在已经代替HashTable
-
ConcurrentHashMap
特点:JDK8中采用CAS无锁算法,线程安全
对应的非并发容器:HashMap -
ConcurrentSkipListMap
特点:线程安全
对应的非并发容器:TreeMap