java之ArrayList源码分析

Wesley13
• 阅读 385

java之ArrayList源码分析

从事javaWeb后端开发,集合的用处可以说是到处可见,数组由于大小是固定的,相对于动态扩容的集合来说,就用的不是那么多了。

今天我们就来分析下ArrayList集合类的源码了,希望可以帮助到你,首先我们还是从集合的入口慢慢深入分析吧。还是一贯风格,看代码咯。

 List<String> stringList=new ArrayList<>();

通过new ArrayList(),我们跟进了这样的代码。

Tips:左右滑动可以看完整代码信息。

 /**

上面的方法就是创建一个空集合,所以在new ArrayList()的时候就帮我们创建了一个空数组,我们还是看下elementData是如何定义的。

transient Object[] elementData; //这是一个Object[]数组用于存储任何类型的数据

好了,下面我们继续看下,我们在使用集合的add()方法时是个怎么样的过程吧,还是直接看程序代码。

上面的add()方法,就是将需要添加的元素e,添加到集合的末尾,也就是数组的末尾了,不过在看下面的流程之前,我们还是先分析一下ensureCapacityInternal()这个方法。

private void ensureCapacityInternal(int minCapacity) {

 这两个方法主要是判断传入的size大小与默认值10进行比较,获取两者之中的最大值,然后调用ensureExplicaitCapacity()方法。

接下来我们可以ensureExplicaitCapacity()方法的代码主要做了什么。代码继续。

      private void ensureExplicitCapacity(int minCapacity) {

上面的方法实现的是对传入的值和数组的length进行比较,满足条件直接进入grow()这个方法了,接下来我们继续看下grow()这个方法吧,看这样的代码需要一些耐心。

     private void grow(int minCapacity) {

这个方法的功能就是,增加容量,以确保它至少可以容纳最小容量参数指定的元素,然后调用Arrays.copyOf()进行拷贝。其实我们再往下面进行代码的分析,就是下面这个方法的调用的。

Tips:左右滑动可以看完整代码信息。

System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));

public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

由于arraycopy是由native关键字修饰的,它是一个本地方法,而不是一个java方法,所以它是运行在本地方法栈的,而不是java栈,建议先进行了解下面的文章java内存区域划分详解好区分本地方法栈和java栈的区别。

上面的就是调用ArrayList类的add()方法的整个流程了,下面我们再看看其他方法吧。

先看下isEmpty()方法的代码。这个比较简单理解,代码看上去,一目了然。

public boolean isEmpty() {

下面继续分析其他方法吧,既然说到今天分享的是ArrayList类的代码分析,不能草草了事对不,也是自己公众号的初衷。

我们调用集合的size()方法就对应着下面的方法,这个size就是数组里面的元素个数大小。

 public int size() {

看下集合是否包含某个元素的contains()方法咯。

public boolean contains(Object o) {

   public int indexOf(Object o) {

上面的indexOf()方法,主要是对传入的对象obj分两种情况进行循环遍历判断,因为add()方法可以添加null值进去的,所以数组里面的元素可能就包含null值。

这时就需要我们按照两种方式,一个是对null值判断,另外一个是正常的元素值,循环遍历整个数组进行一一比较,返回对应的数组的下标值,如果两种遍历都没有找到就返回-1,所以contains()方法调用indexOf()方法就是对返回的数组下标进行了判断。

接下来我们还是慢慢分析吧,由于集合还是比较重要的,需要一点耐心。

我们看下集合的clear()方法的代码。

public void clear() {

clear()方法的功能是循环整个集合(数组)的大小,将每个集合元素都赋值为null,size赋值为0,这样就让JVM的GC机制来帮我们进行无用对象实例进行清除了,建议先移步到这java虚拟机,应该了解一点点先了解一下什么是JVM,本来不打算写下GC了,看来还是有必要的,后面构思一下,再写咯。

喜欢文章的可以关注,转发和分享一下文章,接下来我们看下集合的addAll()方法吧。

Tips:左右滑动可以看完整代码信息。

public boolean addAll(Collection<? extends E> c) {

ok,addAll()方法的功能解释已在代码对应位置说明了。

继续看下根据索引值获取对应元素的get()方法的代码吧,方法的功能和实现在代码中已说明,看注释信息就行了。

public E get(int index) {

既然数组可以转为集合,那么集合也可以转为数组,我们继续看下集合是如何转换为数组的方法toArray()方法。

public Object[] toArray() {

public static <T> T[] copyOf(T[] original, int newLength) {

我们继续看下Arrays.copyOf()方法,这里面涉及到静态工厂方法的内容,建立先看这部分内容java的静态工厂方法,先自己了解下。

其实下面调用的是个静态方法,进行数组之间的拷贝,返回数组。

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {

集合的返回集合元素下标的indexOf()方法在上面的分析过程中已讲解。

上面我们说了indexOf()方法,接下来我们看下集合的lastIndexOf()方法。

public int lastIndexOf(Object o) {

是不是和indexOf()方法的写法很像,一个是从前往后遍历,一个是从后往前遍历进行判断,找不到就返回-1,同样的套路操作,希望可以帮助到你。

下面我们再看最后一个集合的remove()方法吧。

public boolean remove(Object o) {

集合的删除方法和indexOf()方法等都一样,都需要区分null值和非null值的,不过这里面调用了共同的fastRemove()方法,我们继续看下fastRemove()方法。

private void fastRemove(int index) {

好了,关于ArrayList集合类的源码分析到这里就结束了,希望这篇文章可以帮助到你,喜欢文章的可以关注公众号,进行转发和分享下文章,感谢你的阅读,期待遇到更好的自己。

本文分享自微信公众号 - WwpwW(gh_245290c1861a)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这