欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > ArrayList----源码分析

ArrayList----源码分析

2025/10/7 17:03:00 来源:https://blog.csdn.net/weixin_65237252/article/details/140364117  浏览:    关键词:ArrayList----源码分析
源码中的简介:

List接口的可调整数组实现。实现所有可选列表操作,并允许所有元素,包括null。除了实现List接口之外,这个类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大致相当于Vector,只是它是不同步的。)size、isEmpty、get、set、iterator和listiterator操作在常量时间内运行。添加操作在平摊常数时间内运行,即添加n个元素需要O(n)时间。所有其他操作都在线性时间内运行(粗略地说)。与LinkedList实现相比,常数因子较低。每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。它总是至少和列表大小一样大。

当元素被添加到ArrayList中时,它的容量会自动增长。除了添加一个元素具有恒定的平摊时间成本这一事实之外,没有指定增长策略的细节。应用程序可以在添加大量元素之前使用ensureCapacity操作来增加ArrayList实例的容量。这可能会减少增量再分配的数量。注意,这个实现是不同步的。

如果多个线程同时访问一个ArrayList实例,并且至少有一个线程在结构上修改了该列表,则必须在外部进行同步。(结构修改是任何添加或删除一个或多个元素的操作,或者显式地调整后台数组的大小;仅仅设置元素的值并不是对结构的修改。)这通常是通过对一些自然封装列表的对象进行同步来完成的。如果不存在这样的对象,则应该使用集合“包装”列表。synchronizedList方法。这最好在创建时完成,以防止对列表的意外非同步访问:list list = Collections。synchronizedList(新ArrayList(…));

这个类的iterator和listtiterator方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间,以除通过迭代器自己的remove或add方法之外的任何方式修改列表,迭代器将抛出ConcurrentModificationException。因此,在面对并发修改时,迭代器会快速而干净地失败,而不是在未来不确定的时间冒任意的、不确定的行为的风险。请注意,不能保证迭代器的快速故障行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败迭代器在尽最大努力的基础上抛出ConcurrentModificationException。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应该仅用于检测错误。

继承与实现
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
​}

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

ArrayList 继承于 AbstractList ,实现了 List, RandomAccess, Cloneable, java.io.Serializable 这些接口。

List : 表明它是一个列表,支持添加、删除、查找等操作,并且可以通过下标进行访问。

  • RandomAccess :这是一个标志接口,表明实现这个接口的 List 集合是支持 快速随机访问 的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。

  • Cloneable :表明它具有拷贝能力,可以进行深拷贝或浅拷贝操作。

  • Serializable : 表明它可以进行序列化操作,也就是可以将对象转换为字节流进行持久化存储或网络传输,非常方便。

ArrayList 类图

ArrayList 类图

ArrayList 和 Vector 的区别?(了解即可)
  • ArrayListList 的主要实现类,底层使用 Object[]存储,适用于频繁的查找工作,线程不安全 。

  • VectorList 的古老实现类,底层使用Object[] 存储,线程安全。

Arraylist 与 LinkedList 区别?
  • 是否保证线程安全: ArrayListLinkedList 都是不同步的,也就是不保证线程安全;

  • 底层数据结构: ArrayList 底层使用的是 Object 数组LinkedList 底层使用的是 双向链表 数据结构(JDK1.6 之前为循环链表,JDK1.7 取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到!)

  • 插入和删除是否受元素位置的影响:

    • ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是 O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element)),时间复杂度就为 O(n)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。

    • LinkedList 采用链表存储,所以在头尾插入或者删除元素不受元素位置的影响(add(E e)addFirst(E e)addLast(E e)removeFirst()removeLast()),时间复杂度为 O(1),如果是要在指定位置 i 插入和删除元素的话(add(int index, E element)remove(Object o),remove(int index)), 时间复杂度为 O(n) ,因为需要先移动到指定位置再插入和删除。

  • 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList(实现了 RandomAccess 接口) 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。

  • 内存空间占用: ArrayList 的空间浪费主要体现在在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)。

ArrayList扩容(重点)

当我们初始化数组的时候,可以指定初始容量,如果没有选择传入值去初始化容量时,默认容量是10,当我们在不断使用add()方法添加新数据时,如果超过十这个容量时,就会触发扩容机制,在这个时候,我们回去获取当前的容量大小,将其值进行右移一位(实际上对于正数而言就是除以2)在加上原来的容量大小,此时相较于旧容量增长了1.5倍,将这个容量作为新object数组,使用Arrays类中的copyOf()方法将我们的旧数组到新数组中去。

 /*** ArrayList扩容的核心方法。*/private void grow(int minCapacity) {// oldCapacity为旧容量,newCapacity为新容量int oldCapacity = elementData.length;//将oldCapacity 右移一位,其效果相当于oldCapacity /2,//我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,int newCapacity = oldCapacity + (oldCapacity >> 1);//然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//再检查新容量是否超出了ArrayList所定义的最大容量,//若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,//如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Integer.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE。if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity);}
arraylist中的克隆默认为浅克隆,如何深克隆?

// 使用流克隆ArrayList

ArrayList<Dog> clonedList = dogs.stream() .map(Dog::clone).collect(Collectors.toList());

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词