5· | ArrayList | Array |
初始化 | 创建时不需要指定大小 | Array创建时必须指定大小 |
能否扩容 | 根据实际存储的元素动态地扩容或缩容 | 被创建之后就不能改变 |
存储对象 | 只能存储对象 | 基本类型数据+对象 |
API | 支持插入、删除、遍历等常见操作 | 只能按照下标访问其中的元素 |
泛型 | 泛型来确保类型安全 | 无 |
1.2. ArrayList和Vector的区别
最大的区别就是,ArrayList是线程不安全的,效率高;
Vector线程安全,效率低。
1.3. ArrayList可以加null吗
ArrayList 中可以存储任何类型的对象,包括 null 值。
可以,但是不推荐,会让代码难以维护比如忘记做判空处理就会导致空指针异常。
1.4. 时间复杂度
1.5. 扩容机制
2. LinkedList
2.1. 时间复杂度
2.2. 为什么不实现RandomAccess接口
RandomAccess接口支持随机访问,由于 LinkedList 底层数据结构是链表,内存地址不连续,只能通过指针来定位,不支持随机快速访问,所以不能实现 RandomAccess 接口。
2.3. 与ArrayList的区别
ArrayList | LinkedList | |
空间占用 | 小 | 大 |
数据结构 | Object 数组 | 双向链表 |
时间效率 | 除了在容量足够的情况下尾插,和尾插O(1)其余都是O(n) | 除了指定位置的插入删除,其余都是O(n) |
是否支持随机访问 | 是 | 否 |
线程安全否 | 🙅不安全 | 不安全 |
总结:
ArrayList: 适⽤于需要频繁随机访问元素,⽽对插⼊和删除操作要求不那么严格的场景。
LinkedList: 适⽤于需要频繁插⼊和删除操作,⽽对随机访问的需求较少的场景。
Queue
1.ArrayDeque
ArrayList和ArrayDeque的区别
ArrayDeque和LinkedList的区别
相同点:都实现了Deque接口
不同:
ArrayDeque | LinkedList | |
数据结构 | 动态数组+双指针 | 双向链表 |
可null? | 不支持 | 支持 |
性能 | 插入时可能存在扩容过程, 不过均摊后的插入操作依然为 O(1) | 不需要扩容,但是每次插入数据时均需要申请新的堆空间,均摊性能相比更慢。 |
支持随机访问 | 支持 | 不支持 |
总结:
如果需要⾼效的随机访问和更好的空间利⽤,可以选择 ArrayDeque 。
如果需要⾼效的插⼊和删除操作,可以选择 LinkedList 。
2.BlockingQueue
一些常见的实现类:
ArrayBlockingQueue :基于数组实现的有界队列。
LinkedBlockingQueue :基于链表实现的有界或⽆界队列。
PriorityBlockingQueue :基于优先级的⽆界队列。
DelayQueue :⽤于实现延迟任务的⽆界队列。
why:
在多线程之间安全地传递数据,以便在队列为空或队列已满时进⾏等待或阻塞。
how:
1.阻塞操作:
put ⽅法⽤于向队列中添加元素,如果队列已满,则会阻塞直到有空间可⽤。
take ⽅法⽤于从队列中获取元素,如果队列为空,则会阻塞直到有元素可⽤。
2.超时操作:
offer(加) ⽅法⽤于向队列中添加元素,如果队列已满,则会等待指定的超时时间,超时后返回 false 。
poll(拉) ⽅法⽤于从队列中获取元素,如果队列为空,则会等待指定的超时时间,超时后返回 null 。
3.容量限制:可以具有有界或⽆界的容量。有界队列的容量是固定的,⽽⽆界队列可以⽆限制地添 加元素
4.支持公平性:即在多个等待线程中,按照等待时间的顺序选择下⼀个执⾏ 的线程
3.Queue和Deque的区别
Queue:
是单端队列,只能从一端插入元素,另一端删除元素,实现上一般遵循 先进先出(FIFO) 规则。
Queue 扩展了 Collection 的接口,根据 因为容量问题而导致操作失败后处理方式的不同 可以分为两类方法: 一种在操作失败后会抛出异常,另一种则会返回特殊值。
Deque:
是双端队列,在队列的两端均可以插入或删除元素。
扩展了 Queue 的接口, 增加了在队首和队尾进行插入和删除的方法,同样根据失败后处理方式的不同分为两类: