关于Java的集合
Java的集合,也叫容器,由两大接口派生的:Collection和Map
那集合是为了更好的存放数据而对基本数据结构做一层封装
这两个接口的区别就是Collection是存储单个数据,而Map是存储K-V键值对
Collection
先看最上层的Collection,它规范了一些集合的基本方法,这些方法会被实现类实现。
而这些方法也和数据库中的操作相似,无非就是**[增删改查]**以及一些对集合整体的操作(比如说是否为空,大小等)。
底层的实现类继承这些方法并且增加新方法,就出现了不同的数据结构,以方便日常应对不同情况有最好的应对。
先来看子接口SubInterfaces这一层
-
List是有序,可重复的
-
Set是无序,不可重复
-
Query是一种先进先出
FIFO的数据结构
List
List的实现方式有ArrayList以及LinkedList
而他们最大的不同就是,底层数据接口不同:
- ArrayList的底层是数组
- LinkedList的底层是链表
数组的最大特点就是随机存储
random access,物理上数据是连续的
对于查询index来说:
ArrayList的速度是快于LinkedList
数组可以计算偏移量,而链表只能遍历
对于查询对象A来说:
ArrayList和LinkedList是差不多的
数组和链表都只能遍历
对于大多数改查来说,ArrayList因为是数组的原因,效率会更高
那么对于增删来说呢?
数组因为物理上的连续性,当要增删元素在尾部时(除开增加扩容情况),效率也还好,但是如果在其他地方就会导致后续元素都需要移动,效率会比较低。而链表可以轻松的进行增加的操作,快速断开和连接下一个元素。**但是add(int index, E e),remove(E e),remove(int index)方法中,你不得不考虑到index的定位情况,链表需要查找到目标位置会比数组直接计算偏移量更慢,**而且在尾部操作并且数据量大的情况下数组仍然具有优势。
总结
- 改查大部分情况选择ArrayList
- 增删在末尾的选择ArrayList
- 其他情况下,如果时间复杂度相同,选择ArrayList,因为内存使用更有效率。
ArrayList扩容
聊到了数组扩容,那再来了解一下ArrayList的扩容机制。
可以看到ArrayList的扩容机制是二进制右移一位,那右移一位的效果就是除以2,新定义的数组就是原来数组的1.5倍
Vector
Vector和ArrayList一样,底层都是由数组实现的
但是现在已经被弃用了,因为它加了太多的synchronized
虽然它线程安全,但是线程安全的代价就是效率底,所以现在都不在数据结构层面加上synchronied
那么它和ArrayList还有什么区别?
扩容
上面我们了解过ArrayList的扩容机制是新数组是旧数组的1.5倍
那么Vector的扩容机制呢?
Vector的扩容
很好理解vector的扩容机制,因为capacityIncrement我们一般不定义,那么默认情况下扩容成原来数组大小的两倍
Query&Deque
Query是一端进一端出的线性数据结构,而Deque是两端都可以进出的 (单工,全双工?)
Query
Query的api有些特殊,大致分为:抛异常组、返回值组
如果队列空了,像
remove()就会抛出异常,而poll()就会返回null
这两组的功能都一样,那么如何选择呢?
- 同一组API,前后一致
- 根据需求,需要抛异常,那就用抛异常的,反之同理
等待更新...