集合架构
集合与数组的区别
长度 | 内容 | 元素 | |
---|---|---|---|
数组 | 固定 | 基本类型或引用类型 | 同一种类型 |
集合 | 可变 | 引用类型 | 可以存储不同类型(一般存储同种类型) |
Collection集合的方法
集合分类
-
Collection 接口的接口 对象的集合(单列集合)
├ —— List 接口:元素按进入先后有序保存,可重复
│—————├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————└ Vector 接口实现类 数组, 同步, 线程安全
└ ———————└ Stack 是Vector类的实现类
├ —— Set 接口: 仅接收一次,不可重复,并做内部排序
├ —————└ HashSet 使用hash表(数组)存储元素
│———————└ LinkedHashSet 链表维护元素的插入次序
└ —————└ TreeSet 底层实现为二叉树,元素排好序
├ —— Queue接口:
└ —————└ LinkedList 接口实现类(窄化了对LinkedList的方法的访问权限) -
Map 接口 键值对的集合 (双列集合)
├——— Hashtable 接口实现类, 同步, 线程安全
├——— HashMap 接口实现类 ,没有同步, 线程不安全
│—————–├ LinkedHashMap 双向链表和哈希表实现LinkedHashMap详解 分析LinkedHashMap了解LRU
└ ————— └ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└ ——– IdentifyHashMap
List和Set
1. List和Set区别
有序性 | 唯一性 | 元素获取 | 功能 | |
---|---|---|---|---|
list | 按插入顺序排序 | 元素可以重复 | 可通过索引获取 | 查找效率高,插入删除效率低(元素位置改变) |
set | 存储和取出顺序不一致 | 元素唯一 | 不能通过索引 | 查找效率低,插入删除效率高 |
2. List
3. Set
- HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
- LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
- TreeSet底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性(comparable 和 comparator)。
4. 如何使用
Map
- Map 没有继承 Collection 接口
- key 不能重复(由set实现),value可以重复(由Collection实现) 。
方法
HashMap,HashTable,ConccurentHashMap
HashMap:
- Java8以前:拉链法(数组+链表);最坏情况下,所有元素hash值一样,性能从O(1)转为O(n)
- Java8及以后:数组+链表+红黑树;当某一链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间,由O(n)转为O(logn)
- Collections.synchronizedMap(hashMap):将hashmap包装成线程安全
- 仅有hashmap允许key,value为null
- getOrDefault(key, value):如果map中有key,则返回key对应的value值,否则,在map中添加(key, value)键值对
HashTable:
- 线程安全(锁住整个对象),串行执行,效率低
- 实现:数组 + 链表
ConccurentHashMap:
- Java8之前:采用segment分段锁(HashTable锁细粒度化)
- Java8:CAS + synchronized使锁更细化,synchronized只锁定头节点(实现—数组+链表+红黑树)
pub方法:
- 判断Node[]数组是否初始化,没有则进行初始化操作
- 通过hash定位数组的索引坐标,是否有Node节点,如果没有则使用CAS进行添加(链表的头节点),添加失败则进入下次循环
- 检查内部是否正在扩容,帮助一块扩容
- 如果插入元素不为null,则使用synchronized锁住该元素(链表/红黑二叉树的头元素)
- 判断链表长度是否到达临界值(默认为8)
CAS + synchronized:
- 首先使用无锁操作CAS插入头节点,失败则循环重试
- 若头结点已存在,则尝试获取头节点的同步锁,再进行操作
TreeMap
Queue
1. LinkedList
- linkedList为双链表,维护的是一个first和last指针
LinkedList类中定义了三个变量
- size:集合的长度
- first:双向链表头部节点
- last:双向链表尾部节点
常用方法
- get(int index):实现机制–比较传入的索引参数index与集合长度size/2,如果是index小,那么从第一个顺序循环;如果index大,那么从最后一个倒序循环
- add(E e) 和 add(int index, E element)
- remove(Object o) 和 remove(int index)
特有方法:
- LinkedList< Integer > list = new LinkedList<>();(前面必须是 LinkedList;List没有这些方法)
- addFirst()
- addLast()
- removeFirst()
- removeLast()
- getFirst()
- getLast()
2. queue
- Queue queue = new LinkedList();
- add(), offer(): 前者当队列满时,抛出异常,后者返回false
- remove(), polI(): 返回第一个并删除;前者当队列空时,抛出异常,后者返回null
- element(), peek(): 返回第一个;前者当队列空时,抛出异常,后者返回null
3. PriorityQueue
- PriorityQueue是一个基于堆(二叉小顶堆)的无界队列;优先级队列的元素按照自然顺序或者根据构造队列时提供的Comparator进行排序
- 不允许使用 null 元素也不允许插入不可比较的对象(没有实现Comparable接口的对象)
- 头指排指向最小元素
常用方法
- add():插入,同时调整堆结构(保持小/大顶堆)
- peek():获取堆顶元素
- poll():删除堆顶元素,同时调整堆结构
- size()
- isEmpty()
//比较map中的value值
HashMap<Integer, Integer> map = new HashMap<>();
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return map.get(o1) - map.get(o2);
}
}):
补充知识点
1. hashCode 与 equals
Java集合中本质是散列表的类,如HashMap,Hashtable,HashSet,通过hashCode 与 equals保证元素唯一:
- 新加入对象,先比较hashcode值
- 如果冲突,再通过equals比较
为什么重写equals时必须重写hashCode方法:
- 如果两个对象相等,那么它们的hashCode()值一定相同,这里的相等是通过equals()比较两个对象返回true确定的,如果不覆盖hashCode方法,修改的equals无效
2. Comparable和Comparator的区别
- Comparable和Comparator的区别
- 同时存在时,Comparator起作用
Comparable:内部比较器
- int compareTo(Object o)
Comparator:外部比较器
- int compare(Object o1, Object o2)
- return o1 - o2 是升序,return o2 - o1 是降序(当方法的返回值大于0的时候就将数组的前一个数和后一个数做交换)
- 如果类在设计时没有实现内部比较器,后期可以在不用修改原代码的同时实现比较
// Comparator<Integer>():<>中的数据类型取决于arrayList中的数据类型,int 与 Integer 不能混乱
Collections.sort(arrayList, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
object.compareTo():
- Integer: return (x < y) ? -1 : ((x == y) ? 0 : 1);
- Character: return x - y;
- String: 依次比较每个字符(x - y)
3. Collections
- Collections是集合类(Collection)的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序,搜索以及线程安全等各种操作
- Collections.sort(list):默认升序
- Collections.shuffling(list):混排,随机打乱
- Collections.reverse(list):反转
- Collections.fill(list, ‘a’):使用指定元素替换列表中的所有元素
- Collections.copy(list_a, list_b):前一个是目标列表,后一个是源列表
- Collections.min(list)
- Collections.max(list)
- Collections.lastIndexOfSubList(list_a, list_b):返回列表中最后一次出现指定目标列表的起始位置
- Collections.indexOfSubList(list_a, list_b):第一次
- Collections.rotate(list, 1):根据指定的距离循环移动列表元素,可以是负数