插入有序可重复(二) -- ArrayList、Vector

一:概述

ArrayList采用数组作为底层数据结构实现,必然具备高效的随机访问、插入有序、元素可重复等特点。特点介绍在文章List结构解析中已经介绍,不做过多赘述。接下来将从ArrayList的构造、扩容、添加、删除、迭代等几个方面实现深入理解这个常用的集合类

二:构造

在这里插入图片描述
在这里插入图片描述
无参与携带初始化数组大小参数构造为例,首先明确一点ArrayList采用数组实现,任何构造就是对这个数组属性elementData进行赋值。

  • 无参函数赋值DEFAULTCAPACITY_EMPTY_ELEMENTDATA这个长度为0的数组,毫无疑问延迟加载,这也是开发中可以学习使用到的技巧
  • 携带初始化数组大小的构造函数也比较简单,通过判断初始化大小实例化对应长度数组亦或是赋值另外一个长度为0的数组EMPTY_ELEMENTDATA

ArrayList实例化操作的时候对数组实例化采用延迟加载的思想,除了给定正确非负数初始化容量以及使用Colletion构造时都通过两个长度为0的数组进行实例化操作

三:扩容

在这里插入图片描述
在这里插入图片描述
扩容操作得到的新数组容量一定是现有容量 + 现有容量>>1么?答案明显不是,跟随实现查看其扩容算法:

  • minCapacity元素增加后数组最小容量所需,如果数组未进行初始化,则与DEFAULT_CAPACITY默认数组大小10比较得到最大值。若已经初始化则直接将所需最小容量minCapacity作为暂定扩容大小
  • 如果这个最大值大于原有容量,啥也别说了,扩容就完事儿了呗。没有查过再进入核心算法
  • 核心算法就三句话,位移运算获取新计算容量newCapacity,将该容量与最小所需比较得到最大值作为扩容容量。如果最大值大于Integer.MAX_VALUE则使用Integer最大值作为容量

从整个扩容流程必须得到的信息就是初始化ArrayList的时候最好估算其大概容量初始化,避免频繁扩容操作。这也是阿里巴巴规范中的一条,这里的代码就可以得到很好的解释为什么要做这个规定

四:添加

ArrayList熟悉它的继承结构都会想到Collection与List接口定义的方法,其中Collection提供了add()、addAll()元素添加方法,List中针对上述两个方法扩充了List特有的下标操作。元素添加讲解两个点:

  • 第一点就是扩容提到的避免频繁扩容操作,也就是调用addAll()方法的时候注意别一次性添加过大的集合
    在这里插入图片描述
  • 第二点就是讲一下System类提供的arraycopy()方法,如上图所示,共五个参数。被复制数组、被复制数组开始复制下标、目标数组、目标数组开始接收复制数组元素下标、被复制数组复制元素数量
五:删除

在这里插入图片描述
在这里插入图片描述
删除其实也和新增类似,都是通过System.arraycopy()实现,不论是remove()亦或是removeAll()。循环遍历数组,找到删除元素后修改数组,完成删除操作。在这里就可以总结下ArrayList采用了数组实现,那么它每次结构变更的都需要一笔花销。所以ArrayList适合随机访问使用,不适合结构频繁更改时使用

六:迭代

在这里插入图片描述
我记得17年实习就被教育牢记ArrayList只有一个向后迭代器Iterator,LinkedList才具备向前与向后的两个迭代器。但是看完源码是这么回事儿么?明显是错误结论,那么就需要深究这个迭代器到底是什么情况

6.1 接口

在这里插入图片描述
在这里插入图片描述
向后迭代接口Iterator以及向前迭代接口ListIterator,Iterator提供了向后迭代的方法hasNext()判断是否为最后一个元素,next()获取下一个元素以及remove()移除元素的方法。在这个基础上,ListIterator继承接口Iterator,并扩展向前迭代所需的hasPrevious()、previous(),以及替换set()、新增add(),下标获取nextIndex()、previousIndex()

6.2 实现

在这里插入图片描述
首先获取迭代器的方法提供了三组,两组重载的向前迭代和一组向后迭代。那么会问为什么向前迭代会重载一组带有index参数的方法呢?
在这里插入图片描述
看看其具体实现,就是在实例化ListItr内部类的时候传递的这个index,那么这个index到底对于向前迭代的ListItr内部类来说有什么作用?
在这里插入图片描述
看到这里其实就能清晰了,源代码就不继续粘贴出来了。有兴趣可以自己下去看看,这个cursor属性是在Itr内部类中定义的,表示从哪个位置开始迭代。ListItr内部类继承了Itr内部类,自然具备该属性。向后的迭代器并未提供方法设置该属性,所以都是默认从下标0开始向后迭代

七:Vector

Vector就是线程安全嘛,它里面的实现也是简单粗暴。直接在方法上添加Synchronized关键字,但是这个集合目前我使用的就不是很多,因为想要保障线程安全的时候可能不仅仅是涉及到集合操作的安全,大部分情况都会与其它业务逻辑结合设计锁亦或是其它方案

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值