Java集合之ArrayList详解,大厂越来越注重基础了,建议收藏

简介: Java集合之ArrayList详解,大厂越来越注重基础了,建议收藏

1、集合

1.1 JAVA集合关系图

image.png1.2 ArrayList源码分析

1、简介

ArrayList 是 java 集合框架中比较常用的数据结构了。继承自 AbstractList,实现了 List 接口。底层基于数组实现容量大小动态变化。允许 null 的存在。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。


2、重要属性

默认初始容量 10

image.pngEMPTY_ELEMENTDATA与DEFAULTCAPACITY_EMPTY_ELEMENTDATA这两个变量使用在构造函数中


这两个空的数组有什么区别?We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first element is added.区分第一次添加元素的时候知道elementData从空的构造函数还是有参构造函数初始化的。以便于确认如何扩容。

image.png3、构造函数

3.1 无参构造函数

需要注意的是无参构造函数,给elementData赋值的是一个空的数组,在第一次添加元素的时候才把容量扩大为10,不要被注释给误导了。此处可见无参构造器是将DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值给elementData

image.png3.2 构造一个初始容量为initialCapacity的ArrayList

当initialCapacity>0,初始化一个大小为initialCapacity的Object数组,赋值给elementData;当initialCapacity==0,将EMPTY_ELEMENTDATA赋值给elementData;否则,抛出异常。

image.png3.3 通过指定的Collection来初始化一个ArrayList

将Collection转为数组并且赋值给elementData,elementData.length赋值给size;如果size != 0,则判断elementData类型是否为Object[]类型,不是则做一次转换(注意此处其实是一个官方bug解决方案);如果size == 0则将EMPTY_ELEMENTDATA赋值给elementData,相当于new ArrayList(0)

image.png

4、核心方法

4.1 add 操作

ensureCapacityInternal();

每次添加元素到集合中都会先确认集合容量的大小image.pngoldCapacity + (oldCapacity >> 1)


默认将数组的大小扩容到原来的1.5倍


newCapacity - minCapacity < 0


如果扩容后的容量不足,则将所需容量minCapacity赋值给newCapacity,扩容后数组大小就是申请的容量


newCapacity - MAX_ARRAY_SIZE > 0


如果扩容后的数组容量太大,超过了Integer.MAX_VALUE - 8的大小,则数组的大小为hugeCapacity(),(minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;

image.pngimage.png4.2 remove 操作

rangeCheck(index);


检查index是否合法,当index >= size时,抛出IndexOutOfBoundsException异常;


modCount++;


记录集合的操作次数;


E oldValue = elementData(index);


取出移除元素,用于放回给方法调用者;


if (numMoved > 0)


判断当前删除的集合元素是否时数组的最后一个元素,如果不是最后一个元素,则调用System.arraycopy()方法做一次数组拷贝;如果移除的元素是最后一个元素或者在数组复制结束之后,将数组的最后一个元素置为null,等待GC垃圾回收;–size数组的大小减一;

image.png4.3 get 操作

rangeCheck(index);


检查index是否合法,当index >= size时,抛出IndexOutOfBoundsException异常;


elementData(index);


由于ArrayList的底层是由数组实现的,所有获取元素直接调用数组的随机访问即可:image.png5、Iterator

5.1 前言

Java开发初级工程师在使用for遍历集合的时候,由于使用不正确的API方法对集合进行remove()操作,经常会抛出java.util.ConcurrentModificationException,因此我们来从源码的层面仔细的探究一下为什么会产生ConcurrentModificationException以及如何解决这个异常!foreach循环又称增强for循环,是jdk1.5为了简化数组或者和容器遍历而产生,foreach循环的适用范围:对于任何实现了Iterable接口的容器都可以使用foreach循环。foreach语法的冒号后面可以有两种类型,一种是数组类型;一种是实现了Iterable接口的类,因此在使用foreach循环遍历ArrayList的时候,可以看作就是在使用List的迭代器进行遍历


如下代码,foreach遍历list集合时,调用list.remove(s)方法,控制台输出了预期ConcurrentModificationException异常

image.pngimage.pngArrayList定义了一个Itr内部类实现了Iterator接口,Itr内部有三个属性。


cursor:代表的是下一个访问的元素下标;


lastRet:代表的是上一个访问元素的下标,默认值为-1;


expectedModCount:代表的是对ArrayList修改的次数,初始值等于modCount

image.pngimage.pngnext() ;


获取集合中的下一个元素


checkForComodification();


判断modCount与expectedModCount是否相等,不相等抛出ConcurrentModificationException异常


i = cursor;i >= size;i >= elementData.length


判断cursor的大小,如果cursor的值大于集合中元素的个数,抛出NoSuchElementException异常;如果cursor大于了数组的长度抛出ConcurrentModificationException异常。


cursor = i + 1;lastRet = i


如果上述情况均满足,则正常获取下一个元素,cursor和lastRet都自增1

image.pnglastRet < 0;


如果lastRet 小于0,则抛出IllegalStateException异常,由此可以看出,调用remove()之前,必须先调用next()方法重置lastRet的值,否则在lastRet默认值为-1的情况下,对集合中的元素进行移除会直接抛出异常;


checkForComodification();


判断modCount与expectedModCount是否相等,不相等抛出ConcurrentModificationException异常


ArrayList.this.remove(lastRet);


调用ArrayList的remove方法,移除元素


cursor = lastRet;lastRet = -1;expectedModCount = modCount;


将lastRet的值赋值给cursor,相当于-1;将lastRet 重置为-1;将modCount赋值给expectedModCount

image.pngimage.pngimage.pngimage.png



目录
相关文章
|
28天前
|
Java
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
25 0
|
1月前
|
算法 Java 数据处理
Java集合框架的优缺点
Java集合框架的优缺点
|
1月前
|
网络协议 算法 Java
|
1月前
|
安全 算法 Java
Java中的线程安全集合
【2月更文挑战第23天】本文将介绍Java中的线程安全集合,包括它们的使用场景、优缺点以及如何在实际项目中应用。通过阅读本文,你将了解到线程安全集合的重要性以及如何在多线程环境下使用它们来提高程序的性能和稳定性。
33 0
|
1月前
|
存储 算法 Java
JAVA的集合框架
JAVA的集合框架
17 0
|
1月前
|
存储 Java 容器
Java中的集合框架
Java中的集合框架
21 0
|
1月前
|
存储 Java
Java ArrayList 与 LinkedList 的灵活选择
Java ArrayList 类是一个可变大小的数组,位于 java.util 包中。
59 6
|
1月前
|
存储 算法 Java
Java中的集合框架:高效管理数据的关键
Java中的集合框架:高效管理数据的关键
16 0
|
10天前
|
存储 Java 编译器
Java集合丛林:深入了解集合框架的秘密
Java集合丛林:深入了解集合框架的秘密
15 0
Java集合丛林:深入了解集合框架的秘密
|
14天前
|
Java BI
Java 获取周,月,年日期集合(统计图)
Java 获取周,月,年日期集合(统计图)
Java 获取周,月,年日期集合(统计图)

热门文章

最新文章