Java容器之ArrayList

一. ArrayList的类关系图

在这里插入图片描述

二. 关于ArrayList,我们从以下几个方面进行分析

  • 有无顺序
  • 长度是否可变
  • 元素是否可重复
  • 底层实现
  • 线程安全性
  • 优点,特性

三. 分析过程

  • 创建ArrayList,赋值,然后断点查看执行过程
    在这里插入图片描述
    从这张图片中我们可以看到刚刚创建的ArrayList是Object类型的数组.并且长度为0
    在这里插入图片描述
    添加数据之后,数组的长度变了,类型没有变还是Object类型,但是长度为10,而且我们要注意这个数组的标识也由@526变成了@528

在这里插入图片描述 当我们一直添加数据的时候,在超出数组原有长度之后,数组的长度和标识在一次发生了改变.

再此处我们可以得出的结论是:
ArrayList在底层是使用数组进行存储的,第一次声明ArrayList的时候,数组是没有长度的,当第一次赋值的时候,会重新创建一个数组,当数组的长度不不够时,会再次重新创建一个数组.

  • 接下来我们看源码中的add()方法
    在这里插入图片描述
    在add()方法中出现了一个ensureCapacityInternal()方法,传入的参数是size + 1;
    还出现了一个elementData[size++] = e; 将当前add()方法传入的值赋值给一个名为elementData的数组.
    这个数组就是我们在断点中看见的存储数据的数组,size 是 ArrayList的大小(它包含的元素数)
    下面我们看下ensureCapacityInternal()方法又干了什么.
    在这里插入图片描述
    在add()方法中我们可以看到传给ensureCapacityInternal()的方法是size+1也就是当前数组中的元素数加上1,就是如果添加完之后的数组至少应该有这么多位置,不然的话一定会报越界异常.
    在看calculateCapacity(elementData, minCapacity)方法.
    在这里插入图片描述
    这个方法先判断当前的数组是不是刚初始化的数组,如果是行初识话的数组就返回个10,如果不是行初始化的数组就将这个传入的参数返回,也就是添加元素之后的所有元素总数.到现在我们终于找到一个返回的了,我们可以接着看ensureCapacityInternal()方法中调用的ensureExplicitCapacity()方法,这个方法传入的要么是10,要么就是当前添加成功之后的元素总数.
    在这里插入图片描述
    这里的逻辑也非常简单,就是判断一下添加新元素之后的元素总数是否大于数组的总长度.如果大于的话会继续调用grow()方法,传入添加之后的元素总长度,接着往下看.
    在这里插入图片描述
    前面我们说如果添加新元素之后的元素总数大于当前数组的总长度.就会调用grow()方法,传入添加之后的元素总长度.也就是说当前数组还能不能进行继续添加的操作,不能的话就调用grow()方法,这个方法实际上就是ArrayList动态扩容的关键方法.它会将当前数组长度的1.5倍做为新的数组的长度.这个方法中的两个if是判断新的数组长度是否合法,如果不合法的话就会重新复制,最后一段代码就是将原来数据copy到新的数组中.

到此为止add()的方法我们就看完了.这里能总结出来什么呢,就是ArrayList的动态扩容虽然给我们增加了很大的方便,但是在扩容的过程中需要判断的地方也很多,比较耗费资源.

  • 源码就先看这些吧,我们接着说下ArrayList的删除.实际上他在删除的时候更复杂,需要将你删除元素之后的所有数据进行向前移动,这个有兴趣的可以自己跟着源码走一遍.
  • 下面我们看下是否线程安全,发现了一篇写的不错的文章,这里我就不继续啰嗦了,请大家参考:
    Java中不同容器类是否线程安全

总结

  1. ArrayList是有序的,上边虽然没有演示,但是我相信大家都用过 list.get(0) , 其中这个 0 实际上就是元素在数组中的位置,就是数组中的下标
  2. ArrayList长度可变,这个上边我们一起看了源码,除非特出情况,不然是增加原有长度的1.5倍,而且刚声明出来如果不指定长度的话是没有长度的,只有在赋值的时候才会创建一个默认长度为10的数组.
  3. 元素当然是可重复的了,这个没什么好说的吧,我加的都是香蕉.
  4. 底层实现实际上就是一个数组.ArrayList就是对数组进行了一系列的包装,
  5. 线程不安全,关于不安全的原因 Java中不同容器类是否线程安全 这篇文章说的已经很清楚了,如果还不清楚欢迎留言.
  6. 优点,特性,简单的说就是增删速度比较慢,但是查找速度快.但是如果不动态扩容的话,只是在末尾增减一个元素,倒是还能接受,但是如果向指定位置插入元素的话,这个就确实有点复杂了.
  7. 具体的应用场景,这个我感觉还是根据具体业务吧,关于ArrayList的特性和实现原理都清楚了,应用的话应该不是问题吧!
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值