List集合源码解析(ArrayList、Vector篇)

前言

讲List之前,先复习一下基础。首先List是一个接口,并且继承了Collection接口,Collection接口继承了Iterable接口。Collection接口的主要方法有:

boolean add(Object o)添加对象到集合
boolean remove(Object o)删除指定的对象
int size()返回当前集合中元素的数量
boolean contains(Object o)查找集合中是否有指定的对象
boolean isEmpty()判断集合是否为空
Iterator iterator()返回一个迭代器
boolean containsAll(Collection c)查找集合中是否有集合c中的元素
boolean addAll(Collection c)将集合c中所有的元素添加给该集合
void clear()删除集合中所有元素
void removeAll(Collection c)从集合中删除c集合中也有的元素
void retainAll(Collection c)从集合中删除集合c中不包含的元素

        List经常使用的有三个子集,分别是ArrayList、LinkedList、Vector,本文也只针对这三个子集展开。三者的特点概述分别如下:

  • ArrayList底层数据结构是数组,线程不安全
  • LinkedList底层数据结构是链表,线程不安全
  • Vector底层数据结构是数组,线程安全

1、ArrayList

先看一下ArrayList的类图:
在这里插入图片描述

属性

        ArrayList的底层是数组实现的,所以在ArrayList类中,肯定存在一个数组来保存数据,除此之外,数组的初始容量、大小等信息也应该被定义,在源码里长这样:
在这里插入图片描述
        从源码可以看出,ArrayList就是个包装,其底层就是一个数组,只不过它替我们包装和好了对数组的所有常见操作。因此ArrayList的优点就是数组的优点:存取数据快,缺点是扩容慢,需要将所有元素都复制一遍。

构造方法

接下来看一下ArrayList的构造方法:
在这里插入图片描述
        从构造方法可以看出,如果用户指定的容量为0,则初始化数组使用的是空数组EMPTY_ELEMENTDATA,如果用户没有指定大小,则使用的是默认数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA。

add方法

add的方法向数组中增加一个元素,可以说是最重要的方法之一了,先来看一下代码:
在这里插入图片描述
        向容器中添加一个元素时,首先检查增加后的容量有没有越界,第二个方法还多加了一个index的判断,当index大于size或者小于0时,抛出异常。之后它们都调用了ensureCapacityInternal()方法来判断数组是否越界:
在这里插入图片描述
从源码可以看出,判断有无越界只需要比较size++后与length,如果越界,需要将数组容量增长,grow()方法:
在这里插入图片描述
grow()方法首先将容量扩大1.5倍,然后通过copyOf方法将原数组复制到新数组中。copyOf方法:
在这里插入图片描述
        copyOf方法中也是使用System.arraycopy来复制数组的,关于System.arraycopy()的使用可以参考我之前写的JDK中System.arraycopy()的使用。此时判断数组是否越界操作完成,如果越界,创建、复制新数组。然后直接在数组的最后插入元素:

elementData[size++] = e;

get方法

在这里插入图片描述
get方法比较简单,只有两个步骤:
1、检查下标,如果越界,抛出异常
2、返回元素

set方法

在这里插入图片描述
set方法也只有三个步骤:
1、检查下标是否越界
2、设置下标位置为新值
3、返回旧值

remove方法

remove(int index)方法的作用是从数组中删除给定下标:
在这里插入图片描述
remove方法步骤:
1、检查下标是否越界
2、计算第一个需要移动的下标位置
3、将2中计算出来位置及后面的所有元素移动到index位置
4、将最后一个位置的元素删除
5、返回旧值

其中的细节再仔细讲一遍:remove操作其实就是将index后面的元素,向前移动一位。啥意思呢?就相当于一根甘蔗,把中间的砍掉,然后把后面的部分接到前面来。

remove(Object o)方法:
在这里插入图片描述
        remove(Object o)方法是将数组中删除给出的元素,从源码中我们可以看出,ArrayList支持储存null值。当o为null时,我们不能使用equals方法,所以需要先判断o是否为空。fastRemove()代码和remove中的很相似:
在这里插入图片描述

clone方法

clone方法返回了一个复制的ArrayList对象
在这里插入图片描述
        也是通过Arrays.copyOf方法,将底层的数组进行复制。值得注意的是,Arrays.copyOf底层是调用的System.arrayCopy方法,所以这样的复制只是浅复制。System.arrayCopy方法和Arrays.copyOf的区别在于,Arrays.copyOf方法会自动创建一个新的数组,而System.arrayCopy方法要传一个数组进去。

2、Vector

Vector底层也是数组,和ArrayList的区别在于它是同步的,并且它的扩容是2倍。

Vector的源码和ArrayList的非常相似,只是在方法上加了sychronized关键字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值