Java 集合框架:ArrayList 的介绍、使用、原理与源码解析

2024-06-18 1412阅读

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 013 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自己的技术栈的同学。与此同时,本专栏的所有文章,也都会准备充足的代码示例和完善的知识点梳理,因此也十分适合零基础的小白和要准备工作面试的同学学习。当然,我也会在必要的时候进行相关技术深度的技术解读,相信即使是拥有多年 Java 开发经验的从业者和大佬们也会有所收获并找到乐趣。

Java 集合框架:ArrayList 的介绍、使用、原理与源码解析
(图片来源网络,侵删)

本文将从介绍 ArrayList 开始,详细探讨其使用方法、工作原理以及背后的源码实现,帮助读者深入理解并灵活运用 ArrayList,以提升编程效率和代码质量。

在接下来的部分中,我们将首先概述 ArrayList 的基本特性及其在 Java 集合框架中的地位。随后,通过实际代码示例展示如何创建、操作和管理 ArrayList。接着,我们会揭示 ArrayList 的内部工作机制,包括其底层数据结构、扩容策略和性能优化等方面的内容。最后,我们将深入分析 ArrayList 的源码,探讨其设计思想和实现细节,以便读者能够更全面地掌握这一重要的集合类。


文章目录

      • 1、ArrayList 概述
      • 2、ArrayList 的具体实现原理
        • 2.1、ArrayList 底层的数据结构
        • 2.2、ArrayList 随机访问和按索引操作
        • 2.3、ArrayList 的扩容机制
        • 2.4、ArrayList 元素的删除
        • 3、遍历 ArrayList 时移除元素时的问题及解决方案
          • 3.1、在遍历 ArrayList 时移除一个元素时的问题
            • 3.1.1、ConcurrentModificationException
            • 3.1.2、跳过元素
            • 3.2、在遍历 ArrayList 时移除一个元素时推荐的解决方案
              • 3.2.1、使用迭代器的 remove 方法
              • 3.2.2、使用 Java 8 的 removeIf 方法
              • 3.2.3、使用逆向遍历
              • 4、ArrayList 的使用(常用方法)
                • 4.1、ArrayList 的常用方法
                • 4.2、Collections 类中涉及 ArrayList 的常用方法

                  1、ArrayList 概述

                  ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。

                  ArrayList 是基于数组实现的,相当于动态数组,其容量能动态增长,类似于 C 语言中的动态申请内存,动态增长内存。

                  ArrayList 的每个实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是大于等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造 ArrayList 时指定其容量。

                  ArrayList 在被添加大量元素前,应用程序可以使用 ensureCapacity() 操作来指定 ArrayList 实例的容量,这可以减少递增式再分配的数量。

                  ArrayList 是非线程安全的,只能在单线程环境下使用,多线程环境下可以考虑用 Collections.synchronizedList(List l) 函数返回一个线程安全的 ArrayList 类,也可以使用 java.util.concurrent 并发包下的 CopyOnWriteArrayList 类。


                  2、ArrayList 的具体实现原理

                  ArrayList 的原理其实很好概括和理解,简单概括就是:我们先在 ArrayList 中定义声明一个 Java 数组,接着定义对这个 Java 数组的,添加、删除、修改以及查询这四类方法。这其中最值得注意的是两点,一个是,由于底层操作的是数组,所以在进行删除操作是会涉及对大量元素的移动;另一个则是在增加元素并达到底层 Java 数组容量后的数组扩容问题。

                  2.1、ArrayList 底层的数据结构

                  ArrayList 在 Java 中是基于数组实现的动态数组,其核心数据结构是一个 Object 类型的数组 elementData,用于存储元素。

                  package java.util;
                  import ...
                    
                  public class ArrayList extends AbstractList
                          implements List, RandomAccess, Cloneable, java.io.Serializable
                  {
                      
                    	// 省略其他方法和实现细节
                    	...
                      // 默认初始容量
                      private static final int DEFAULT_CAPACITY = 10;
                      // 用于空实例的共享空数组实例
                      private static final Object[] EMPTY_ELEMENTDATA = {};
                      // 用于默认大小空实例的共享空数组实例
                      // 当添加第一个元素时,会扩展为 DEFAULT_CAPACITY
                      private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
                      // 用于存储 ArrayList 元素的数组缓冲区
                      // transient 关键字表示该字段不会被序列化
                      transient Object[] elementData;
                      // ArrayList 当前包含的元素数量
                      private int size;
                      /`
                       * 构造一个具有指定初始容量的空列表。
                       *
                       * @param  initialCapacity  列表的初始容量
                       * @throws IllegalArgumentException 如果指定的初始容量为负数
                       */
                      public ArrayList(int initialCapacity) {
                          if (initialCapacity > 0) {
                              this.elementData = new Object[initialCapacity]; // 初始化指定容量的数组
                          } else if (initialCapacity == 0) {
                              this.elementData = EMPTY_ELEMENTDATA; // 使用共享的空数组实例
                          } else {
                              throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); // 抛出非法参数异常
                          }
                      }
                      /`
                       * 构造一个初始容量为 10 的空列表。
                       */
                      public ArrayList() {
                          this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // 使用默认大小的空数组实例
                      }
                      /`
                       * 构造一个包含指定集合元素的列表,这些元素按该集合的迭代器返回的顺序排列。
                       *
                       * @param c 要放入列表中的集合
                       * @throws NullPointerException 如果指定的集合为 null
                       */
                      public ArrayList(Collection c)
                  • 功能:从列表中移除指定集合中也存在的所有元素。
                  • 用例:
                    ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "b"));
                    list.removeAll(Collections.singleton("b"));  // 移除所有 "b"
                    
                    1. retainAll(Collection c)
                    • 功能:仅保留列表中那些也包含在指定集合中的元素。
                    • 用例:
                      ArrayList list = new ArrayList(Arrays.asList("a", "b", "c"));
                      list.retainAll(Arrays.asList("a", "b"));  // 保留 "a" 和 "b"
                      
                      1. containsAll(Collection c)
                      • 功能:如果列表包含指定集合中的所有元素,则返回 true。
                      • 用例:
                        ArrayList list = new ArrayList(Arrays.asList("a", "b", "c"));
                        boolean contains = list.containsAll(Arrays.asList("a", "b"));  // 检查是否包含 "a" 和 "b"
                        
                        1. clear()
                        • 功能:移除列表中的所有元素。
                        • 用例:
                          ArrayList list = new ArrayList(Arrays.asList("a", "b", "c"));
                          list.clear();  // 清空列表
                          
                          4.2、Collections 类中涉及 ArrayList 的常用方法
                          1. sort(List list)
                          • 功能:对列表进行排序(自然顺序)。
                          • 用例:
                            ArrayList list = new ArrayList(Arrays.asList(3, 1, 4, 1, 5));
                            Collections.sort(list); // 对列表排序
                            
                            1. reverse(List list)
                            • 功能:反转列表中元素的顺序。

                            • 用例:

                              ArrayList list = new ArrayList(Arrays.asList(1, 2, 3));
                              Collections.reverse(list); // 列表变为 [3, 2, 1]
                              
                              1. shuffle(List list)
                              • 功能:随机打乱列表中元素的顺序。
                              • 用例:
                                ArrayList list = new ArrayList(Arrays.asList(1, 2, 3));
                                Collections.shuffle(list); // 打乱列表元素的顺序
                                
                                1. binarySearch(List c, Object o)
                                • 功能:从集合中删除指定的元素。
                                • 用例:
                                  ArrayList list = new ArrayList(Arrays.asList(1, 2, 3, 2, 1));
                                  list.removeAll(Collections.singleton(1));  // 删除所有1
                                  
                                  1. copy(List c, Object o)
                                  • 功能:返回指定元素在集合中出现的次数。
                                  • 用例:
                                    ArrayList list = new ArrayList(Arrays.asList(1, 2, 1, 3));
                                    int freq = Collections.frequency(list, 1);  // 计算1在列表中出现的次数
                                    

                                    13, disjoint(Collection c1, Collection c2)

                                    • 功能:如果两个集合没有共同的元素,则返回true。
                                    • 用例:
                                      ArrayList list1 = new ArrayList(Arrays.asList(1, 2, 3));
                                      ArrayList list2 = new ArrayList(Arrays.asList(4, 5, 6));
                                      boolean isDisjoint = Collections.disjoint(list1, list2);  // 检查两个列表是否没有共同元素
                                      
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]