千家信息网

java中ArrayList怎么用

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,小编给大家分享一下java中ArrayList怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!ArrayList构造器
千家信息网最后更新 2026年11月02日java中ArrayList怎么用

小编给大家分享一下java中ArrayList怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

ArrayList构造器简介

在java中,一切皆对象,一切操作又离不开对象,ArrayList也是如此,所以想要研究ArrayList是如何工作的就要从ArrayList的构造开始。

ArrayList提供了三个构造,分别是不带任何参数的构造器、接受一个int类型值的构造器和接受一个带泛型的Collection的构造器,首先我们从最简单的没有任何参数、也是大多数人最常用的这个构造器开始。

无参数构造器

打开源码可以看到无参数构造器非常的简单,只有一行代码,代码如下:

其中DEFAULTCAPACITY_EMPTY_ELEMENTDATA是ArrayList中定义的一个静态的不可变的空数组,而elementData则是ArrayList保存实际数据使用的数组引用,也就是说如果用默认无参数构造器构造ArrayList的话是没有初始数组的(为空,所有实例共享)。

接收一个int类型值的构造器

打开源码,可以看到如下代码:

可以看到,当传入参数为0时与不传参数的逻辑是一致的,当传入参数大于0时ArrayList会构建一个与传入参数为大小的Object数组,而当传入参数小于0时,就会抛出一个非法参数异常(IllegalArgumentException)了。

接收一个Collection参数的构造器

仍然是打开源码查看,可以看到以下代码:

首先是将传入参数转换为数组,然后将这个数组引用赋值给ArrayList内部维护的数组引用,如果这个数组的长度是0时你会发现这时的行为又与空参数构造器的行为一致了,而当这个数组长度不是0时,ArrayList做了一些小动作,对于这些小动作,注释也写的很清楚了,c.toArray might (incorrectly) not return Object[],也就是说这个数组有可能不是Object类型的数组(在不正确的情况下,这个是由JDK本身的一个BUG造成的,具体的可以去JDK的BUG库http://bugs.java.com/bugdatabase/中查找BUG ID为6260652的BUG,有兴趣的同学可以自行查找阅读,本文不去详细介绍),所以为了保证代码的健壮性,就加了这么一个类型检查,而为什么要检查这个数组是不是Object类型的呢?这个很简单,就是因为如果此处引用的是一个String类型的数组,后续如果往里边放入一个非String类型的数据就会报错,而这个错误通常是到运行时才会发现的。

ArrayList的构造器介绍到此就结束了,下面开始介绍ArrayList的方法,由于篇幅有限,所以本文仅挑选几个ArrayList初级使用者最常用的方法介绍。

public boolean add(E e)

这个方法是最常用的一个方法,其作用就是将一个新元素加入到当前list的尾部,源码如下:

可以看到这个方法非常简洁,调用了另外一个方法ensureCapacityInternal,然后将数据填充进数组,更新size,整个方法就结束了,固定返回的true,也就是该方法只要不抛出异常肯定会返回true,至于ensureCapacityInternal方法会在后面讲解,ArrayList中也多次调用到了该方法,算是核心方法之一。可以很容易看出,该方法的渐进时间复杂度为O(1)(不扩容的情况下)。

public void add(int index, E element)

这个方法的作用是将一个元素插入到list的指定位置,源码如下:

首先是第一行,第一行很简单,看方法名就知道是范围检测,具体的行为就是检测当前传入的index参数是否大于当前size或者小于0,如果大于当前size或者小于0的话就抛出一个索引越界异常(IndexOutOfBoundsException),然后该方法也调用了ensureCapacityInternal方法,然后就是将参数index位置和index位置之后的数据给全部后移一位,也就是说该方法插入的位置后边的数据越多,那么要移位的数据也就越多,效率也就越低。该方法的最坏时间复杂度为O(n)(不扩容的情况下),其中n等于ArrayList的size。

public E remove(int index)

该方法是将指定索引处的数据删除,源码如下:

该方法的第一行仍然是范围检查,不同的是只要index不是大于等于ArrayList的size就不会抛出异常,但是这一行不抛出异常不代表后边就不会抛出异常,该处没有显示检查是否小于0是因为后边第三行有从数组中取数据这个操作,而对于该操作,如果index小于0的话是一定会抛出异常的。然后第四行计算了一下需要移动位置的元素,也就是index位置之后还有多少元素需要前移,当该值大于0时(注:只会大于0或者等于0,不可能小于0),说明有需要移动的元素,将这numMoved个元素统统前移一位,然后将原数组的最后一位设置为null以便于GC可以清除该处引用(注:因为使用的System.arraycopy方法,所以并不会删除数据,只会复制,而原来数组的最后一位虽然已经复制前移,而且size也已经更新,获取不到该引用的数据,但是该引用仍然存在,并没有被清空,所以下次GC的时候如果该处没有填充新的值覆盖,那么这个引用将不会被回收并且也获取不到该处的值,需要详细了解的可以看一下java的GC原理或者加我Q1213812243询问^_^)。最后,将第三行获取到的该位置的数据返回,至此,该方法结束。由于该方法也需要原数组数据的移位,所以很容易可以得出该方法的最坏时间复杂度也是O(n),其中n等于ArrayList的size。

public boolean remove(Object o)

该方法是从ArrayList中删除指定元素,更准确的说是从ArrayList中删除第一个与指定元素相同的元素,话不多说上源码:

由该方法的实现可以看出,如果传入的元素为null时,该方法将删除ArrayList中的第一个null元素(不是全部的null元素)并返回true,如果传入元素不为null时,该方法将调用传入元素的equals方法与ArrayList中的元素一一对比,直到发现第一个相同的元素,然后删除并返回true,如果遍历整个list发现都没有与传入对象相同的对象,那么该方法将返回false表示删除失败。这里要注意一个小细节,该方法实际删除元素操作用的是fastRemove而不是上一个提到的public E remove(int index),而根据命名可以猜测出fastRemove方法删除是比较快的,但是具体是哪儿快了呢?首先查看源码:

与上一个remove方法对比,很容易可以看出这个方法由于是内部使用的,也不需要返回值,所以并没有去检查参数index的范围合法性,也没有把要删除的数据取出,省了这两个开销,虽然省的并不多,但是如果在一个大型系统中,这样的小开销累计起来也是很大的。同样的,很容易可以得出该方法的时间渐进复杂度为O(n),其中n等于ArrayList的size。

public E get(int index)

该方法是从ArrayList中取数据,数据存起来的目的就是为了后续的使用,所以该方法是最常用也是最重要的一个方法,源码如下:

可以看出,该方法很简单,仅仅检查了一下参数的范围,然后就直接取数据返回了,而elementData方法也只有短短的一行

很容易可以得出该方法的时间渐进复杂度为O(1)。

private void ensureCapacityInternal(int minCapacity)

这个方法是前面提及的但是并没有具体介绍的一个方法,把这个方法放在最后是因为这个方法算是ArrayList的一个核心方法,该方法的作用就是检查内部数组是否够用,如果不够用的话自动扩充,源码如下:

该方法又调用了ensureExplicitCapacity方法,而ensureExplicitCapacity方法的源码如下:

该方法判断了一下参数是否大于当前数组的最大长度,如果大于那么调用grow方法扩容,如果不大于那么不做任何操作。grow方法源码如下:

该方法也很简单,只有7行代码,在第一行首先计算出原数组的长度,然后第二行计算出原数组长度扩充1.5倍后的新的长度(注:右移一位等价于除以2),第三行判断了扩充1.5倍后的长度是否大于参数(实际需要的长度),如果小于该长度的话将扩充后的新长度更新为参数值(minCapacity),然后在第5行判断了扩充后的长度是否大于MAX_ARRAY_SIZE这个静态变量,如果大于该长度的话使用hugeCapacity方法确定是否溢出(即数组长度是否大于Integer.MAX_VALUE),该方法进入后正常情况是肯定会返回Integer.MAX_VALUE,因为外部已经判断过minCapacity是否大于MAX_ARRAY_SIZE了,只有大于该值才能进来,所以此方法必定返回Integer.MAX_VALUE,ArrayList内部维护的数组长度也达到了最大值Integer.MAX_VALUE,而此时当list再次填充满需要扩容的时候,传到此处的参数为(size+1)将是一个负数(Integer溢出),然后调用hugeCapacity方法时会发现传进来的参数是一个负数,说明已经溢出了,将会抛出一个异常。(注:如果对此处的溢出不理解可以加QQ1213812243询问或者自行百度)

该方法的最后一行会将数据从老数组迁移至新数组,而老数组由于没有了引用所以会在后续的GC中被清除。很容易可以得出该方法的时间渐进复杂度为O(n)(需要扩容的情况下,不需要扩容为O(1)),其中n等于当前ArrayList的size。

以上是"java中ArrayList怎么用"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

方法 数组 参数 元素 数据 长度 源码 构造器 一行 位置 类型 检查 复杂 代码 复杂度 就是 时间 也就是 情况 只有 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海挚品互联网科技有限公司 互联网科技工作委员会 A股互联网金融科技公司 互联网科技未来 互联网科技公司发展 深圳互联网络科技有限公司 互联网科技媒体 伴你行互联网科技有限公司 互联网科技咨询 互联网金融科技委员会 互联网科技实习生岗位职责 小米互联网科技园设置 互联网与医疗科技 科技互联网的核心竞争力 山东子淼互联网科技有限公司 元气玛特互联网科技公司是外包吗 互联网的科技体现在哪里 科技互联网专业务虚会材料 六子台科技互联网展会 知域互联网科技有限公司官网 关于新基建和互联网科技 九亚互联网科技 北京互联网络科技有限公司 互联网 视角下的科技创新 广州紫鲸互联网科技 成都互联网科技公司工作好不好 开一家科技互联网公司需要多少钱 青海科技产业互联网发展 济南有互联网科技公司吗 银川新华互联网科技学校原画
0