美文网首页js css html
Java ArrayList源码解读

Java ArrayList源码解读

作者: 在岁月中远行 | 来源:发表于2023-02-07 02:17 被阅读0次

1 ArrayList简介

ArrayList是一个数组队列,相当于动态数组。与JAVA中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List,RandomAccess,Clone,java.io.Seriaizable这些接口。

ArrayList继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加,删除,修改,遍历等功能。

ArrayList实现了RandomAccess接口,提供了随机访问功能。我们可以通过元素的序号快速获取元素对象,这就是随机访问。

ArrayList实现了Cloneable接口,覆盖了函数clone,能被克隆。

ArrayList实现了java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

ArrayList的操作不是线程安全的,建议在单线程中使用,而在多线程可以选择CopyOnWriteArrayList,Vector不建议使用(大部分方法直接被synronized直接修饰)

2 ArrayList源码分析

ArrayList说明支持泛型的。

ArrayList继承了抽象类AbstractList,而让AbstractList先实现了List接口,而不是让ArrayList直接继承List。

主要原因:接口中全是抽象的方法,而抽象类中可以有抽象方法,也有普通的方法,利用了这一点,让AbstractList去实现接口中一些通用的方法,而具体的类ArrayList继承了AbstractList,拿到一些通用的方法,然后自己可以再加上一些普通方法的逻辑。这样就把继承结构最底层的类中通用的方法接口都实现了。让代码更简洁。

实现了RandomAccess接口,在ArrayList中我们可以通过元素的序号快速获取元素对象,这就是快速随机访问。

实现了Cloneable接口,就可以使用Object.clone方法了。

实现了Serializable:表示该类具有序列化功能,该类可以被序列化,就是能够从类变成字节流传输,然后还能从字节流变成原来的类。

类的属性:

重要属性transient Object[] elementData 它的length代表ArrayList的容量。

构造方法:

ArrayList(int initialCapactity):构造一个指定容量initialCapactity的空ArrayList,这是一个带初始容量大小的有参构造函数。

ArrayList():构造一个初始容量为10的空列表,如果我们创建ArrayList对象的时候不传入参数,则使用无参构造方法创建ArrayList对象,从前面我们知道DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空的Object[],这个空的Object[]会给个默认容量为10,但是现在我们是没看到这个容量为10,答案是第一次调用add()方法时,elementData将会变成默认的长度10。这个后面也会提到。

主要方法:

get()方法:

先越界检出,然后返回elementData数组的索引index。

set()方法

从elementData数组中取出旧值,然后把传进来的element赋值给elementData[index],然后返回旧值,看来这个方法是有返回值的,返回的是旧值。

add()方法:

有两个,一个带一个参数的,一个是带两个参数的。

先分析add(E e)这个方法。

先调用了确保内部容量方法,如果ArrayList是通过无参构造方法创建的话,此时size为0,然后size+1作为参数传递给ensureCapacityInternal方法。

由于是通过无参构造的那么minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);这行就会执行。接着就是minCapacity = DEFAULT_CAPACITY也就是10。

接着调用ensureExplicitCapacity(10),当最小容量10>数组容量数组的长度时,那么久进行扩容调用grow方法。

先获取当前数组的容量

进行扩容,新的容量=当前容量+当前容量/2,也就是扩容一次是1.5倍。

如果扩容后的容量还是小于想要的最小容量,那么直接将最小容量赋值给新的容量。

后面是扩容的容量临界值处理。

新的容量大小确定好之后,就copy数组,改变容量大小。

add(E e)第二种情况就是调用了有参构造方法传入了容量值。

add(int index, E element)方法:

越界检查,确保容量

对数组进行复制处理,目的就是空出index的位置插入element,并将index的元素位移一个位置

将指定的index位置赋值

ArrayList实际大小加1。

remove方法:

结构性修改次数+1

记录索引处的元素

计算删除元素,需要左移的元素个数

如果有需要左移的元素,就移动

size减1,然后将索引为size-1处的元素设为null,为了让GC起作用,显式地将最后一个位置为null值。

最后将旧值返回

indexOf()方法:返回此列表中指定元素的第一个出现项的索引,如果该列表不包含该元素,则返回-1。

分null和不为null两个逻辑,就是遍历elementData数组,找到了就返回index。这里看出来对ArrayList的操作都是对elementData数组操作。

clear()方法:

modCount++;检测快速失败的一种标志该变量加1 

循环遍历赋值为null

ArrayList的大小设置为0

相关文章

网友评论

    本文标题:Java ArrayList源码解读

    本文链接:https://www.haomeiwen.com/subject/bsdxkdtx.html