个人笔记_集合

219 阅读3分钟

关于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的定位情况,链表需要查找到目标位置会比数组直接计算偏移量更慢,**而且在尾部操作并且数据量大的情况下数组仍然具有优势。

总结

  1. 改查大部分情况选择ArrayList
  2. 增删在末尾的选择ArrayList
  3. 其他情况下,如果时间复杂度相同,选择ArrayList,因为内存使用更有效率。

ArrayList扩容

聊到了数组扩容,那再来了解一下ArrayList的扩容机制。

图片

可以看到ArrayList的扩容机制是二进制右移一位,那右移一位的效果就是除以2,新定义的数组就是原来数组的1.5倍


Vector

Vector和ArrayList一样,底层都是由数组实现的

但是现在已经被弃用了,因为它加了太多的synchronized

虽然它线程安全,但是线程安全的代价就是效率底,所以现在都不在数据结构层面加上synchronied

那么它和ArrayList还有什么区别?

扩容

上面我们了解过ArrayList的扩容机制是新数组是旧数组的1.5倍

那么Vector的扩容机制呢?

Vector的扩容

image.png

很好理解vector的扩容机制,因为capacityIncrement我们一般不定义,那么默认情况下扩容成原来数组大小的两倍

Query&Deque

Query是一端进一端出的线性数据结构,而Deque是两端都可以进出的 (单工,全双工?)

Query

Query的api有些特殊,大致分为:抛异常组、返回值组

如果队列空了,像remove()就会抛出异常,而poll()就会返回null

这两组的功能都一样,那么如何选择呢?

  • 同一组API,前后一致
  • 根据需求,需要抛异常,那就用抛异常的,反之同理

等待更新...