Fork me on GitHub

List集合

List接口

image-20230326181756960

ArrayList

结论

image-20230320210100814

底层原理

执行的代码image-20230320222822663

1.无参构造

elementData 就是ArrayList底层元素存放的数组

image-20230320211303399image-20230320211309812

2.有参构造
  • 两个只是构造方法不一样,但是后面的 addgrow 是一样的

    只不过是直接将 elementData初始化大小为8的数组

    image-20230320223051524
3.集合 add 方法
image-20230320211836288

判断当前的 capacity容量是否充足,size 当前集合的元素的数量(每一次进入 add 方法的时候,size的位置就是存放add的元素的下标,存放完之后 size++),第一次 add ,size 为 0image-20230320212004330

  • 进入ensureCapacityInternal确认容量内部 的方法,modCount 记录当前的集合被修改次数,防止多个线程修改,抛出异常,fail-fast

    如果 if 成立,就表示 需要的最小容量已经大于当前容量了,所以当前容量需要扩大,进入 grow 扩容

    minCapacity指的是源数组中存储的元素个数加上将要存储的元素个数,这里第一次add()时,minCapacity为1,数组的长度为0,数组内存不够,故进行扩充

    elementData.length是数组(集合)容量的大小

image-20230320215031945

扩容,进入 grow 方法,最后通过 Array.copyOf 方法复制旧数组并且扩容返回新的数组

  • 右移,相当于是除以2,左移,相当于是乘以2

  • 所以 newCapacity = oldCapacity + (oldCapacity >> 1)

    就是相当于 扩容了oldCapacity 的1.5倍

  • 下面代码的第一个 if 判断,是因为第一次扩容为 10 的时候,minCapacity=10,newCapacity、oldCapacity 都为0这是对一次进行扩容的弥补措施

image-20230320215301355

ArrayList和Vector区别

image-20230320231455113

Vector

线程安全的,synchronized加锁

底层原理

执行代码image-20230320225047171

1.无参构造

this 就是调用本类的 构造器

image-20230320225115565image-20230320225124799

  • 所以,我们可以指定 有参构造,或者两个参数的构造方法

    capacityIncrement第一次进行扩容的大小image-20230320225310449

2.进入 add 方法

ArrayList 大体一样image-20230320225511324

image-20230320225550594

3.满足条件。进入 grow 扩容方法
  • capacityIncrement 扩容的大小,创建 vector 没有指定的话,默认是 0

    那么 capacityIncrement一辈子就都是 0 了,所以每一次扩容都是 oldCapacity + oldCapacity,2倍

  • 如果创建 vector 的时候指定了 capacityIncrement ,那么之后的每一次扩容都是按照 capacityIncrement 大小进行扩容,就不是 2 倍了

image-20230320225809891

LinkedList

双向链表

底层原理

执行代码image-20230321145249436

1.无参构造

就是简单的初始化 属性image-20230321102829416

有参数的构造image-20230321103358951E 是创建 linkList 对象指定的泛型

2.add 方法
image-20230321102927854
  • linkLast 方法就是,将元素 element 添加到 linkList 链表的 last 位置

    就是一个简单的算法逻辑,就是 l 是复制的 last,然后创建一个新的节点,存储 add 元素,新节点的 prev 指向 l(也就是上次的last),然而 last 被赋值为新节点 newNode

    这就完成了 last 还是 last,并且 newNode 的 prev 指向的是上一次的 last

image-20230321104145559
3.remove 方法

默认的是 删除第一个节点

image-20230321104652386image-20230321105000544

  • 进入 unlinkFirst 删除节点的方法,返回值是 删除的元素 element

    如果不加 final 的话,同样会被 gc 干掉

image-20230321113116932

ArrayList和LinkedList区别

两者都是线程不安全

  • 链表因为只能从头节点开始遍历,只能通过顺次指针访问,查询效率低,所以 查询和修改某一个节点 性能较差

    因为 链表 不同node节点对象是通过 指针 连接起来的,是不连续的内存地址

    链表则必须是顺序访问,不能随机访问(必须从头节点开始进行遍历,因为不知道内存地址

    底层维护的是 Node 对象
    链表可以随意扩大容量

  • ArrayList 底层是维护的一个数组,数组是连续的内存地址,所以使用方便 ,查询效率 比链表 高

    数组可以随机访问其中的元素 (因为内存地址是连续的,可以通过计算得出访问的元素的地址

    数组则不能随便扩容,只能通过 copy 重新创建一个数组进行转移扩容

image-20230321115902189image-20230321115928901

posted @ 2023-06-15 00:52  小小俊少  阅读(4)  评论(0编辑  收藏  举报