Bootstrap

深入理解Java ArrayList集合及其源码详解

一、ArrayList简单概述

出身

  • ArrayList是Java集合框架(Java Collections Framework)中List接口的一个实现。
  • 它底层是一个动态数组,用于存储一组有序的元素。
    • 注意:这个有序不是排序后的“有序”;而是创建时有序的存储,即取出的时候跟插入时的顺序一致,比如:排队的时候一个接一个的排,而不是乱排,这样的队伍就是有序的。

优点:

  • ArrayList可以通过下标访问,提供了更高效的随机访问性能,同时还可以根据需要自动调整其大小。

缺点:

  • ArrayList的删除元素操作可能会导致性能问题,因为删除元素时需要将后面的元素向前移一位。
  • 同样ArrayList的插入元素操作可能会导致性能问题,因为插入元素时需要将后面的元素向后移一位。

ArrayList的原理

ArrayList基于数组实现,这意味着它可以使用索引快速地访问和修改元素。当数组中的元素达到其容量上限时,ArrayList会创建一个新的、更大的数组,并将现有元素复制到新数组中。这个过程称为扩容(Resizing)。扩容过程是自动进行的,开发者无需手动处理。

ArrayList的特性

  1. 动态扩容:ArrayList可以根据需要自动调整其大小。当元素数量超过当前容量时,它会创建一个新的、更大的数组,并将现有元素复制到新数组中。

  2. 随机访问:由于ArrayList是基于数组实现的,因此它提供了快速的随机访问性能。通过索引,可以直接访问和修改元素。

  3. 重复元素:ArrayList可以包含重复元素。

二、ArrayList的源码详解

属性

 private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 默认初始容量。
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 用于空实例的共享空数组实例。
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 用于默认大小的空实例的共享空数组实例。
     * 我们将其与EMPTY_ELEMENTDATA区分开来,以了解添加第一个元素时要膨胀多少。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 存储ArrayList元素的数组缓冲区。
     * ArrayList的容量就是这个数组缓冲区的长度。
     * 添加第一个元素时,任何elementData==DEFAULTCAPACITY_empty_elementData
     * 的空ArrayList都将扩展为DEFAULT_CAPACITY。
     */
    transient Object[] elementData;

    /**
     * ArrayList的大小(包含的元素数)。
     */
    private int size;

构造方法


 public ArrayList(int initialCapacity) {// 构造一个具有指定初始容量的空列表。
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {// 传入参数为0,构造空实例的共享空数组实例
            this.elementData = EMPTY_ELEMENTDATA;
        } else {//传入数据错误,抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    
    public ArrayList() {//构造一个初始容量为 10 的空列表。
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//默认值是10
    }

   //构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

常用方法

  • 插入元素 boolean add(E e)
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  //容量加一
        elementData[size++] = e;// 从末尾加入
        return true;
    }
  • 指定位置插入 void add(int index, E element)
  public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  //容量加一
        // 调用System.arraycopy创建新数组,再将旧数组拷贝进去
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }
  • 根据下标取元素 public E get(int index)
    public E get(int index) {
    // 调用下标范围检查方法,检查下标是否越界,若越界抛出IndexOutOfBoundsException
        rangeCheck(index);

        return elementData(index);//调用查找元素方法,返回元素
    }
  • 根据下标用指定元素替换指定下标元素,并返回旧元素
  • public E set(int index, E element)
   public E set(int index, E element) {
   // 调用下标范围检查方法,检查下标是否越界,若越界抛出IndexOutOfBoundsException
        rangeCheck(index);
		//寻找被替换元素
        E oldValue = elementData(index);// 调用查找元素方法,返回元素
        elementData[index] = element;// 用新元素覆盖旧元素
        return oldValue;// 返回旧元素
    }
  • 移除此列表中指定位置上的元素public E remove(int index)
    public E remove(int index) {
     // 调用下标范围检查方法,检查下标是否越界,若越界抛出IndexOutOfBoundsException
        rangeCheck(index);

        modCount++;
        //寻找被移除元素
        E oldValue = elementData(index);
		//判断被移除元素是否是末尾元素,是的话不用将其他元素向前移动,提高移除效率
        int numMoved = size - index - 1;
        if (numMoved > 0)
        //将后面其他元素向前移动
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null;//末尾设为null

        return oldValue;//返回被移除元素
    }
  • 移除此列表中的所有元素 void clear()
  public void clear() {
        modCount++;

        // 遍历列表,并将所以元素设为null
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;//容量设为0
    }

三、ArrayList常用方法的演示

  1. 创建ArrayList:要创建一个ArrayList,可以使用以下构造方法:

    • 无参构造方法:ArrayList()
    • 带有一个参数的构造方法:ArrayList(Collection<? extends E> c)
    • 带有一个初始容量参数的构造方法:ArrayList(int initialCapacity)
  2. 添加元素:可以使用add(E e)方法向ArrayList中添加元素。如果需要添加多个元素,可以使用addAll(Collection<? extends E> c)方法。

  3. 删除元素:可以使用remove(Object o)方法删除指定元素的第一个匹配项。如果要删除所有匹配的元素,可以使用removeAll(Collection<?> c)方法。

  4. 修改元素:可以使用set(int index, E element)方法修改指定索引处的元素。

  5. 访问元素:可以使用get(int index)方法通过索引访问元素。

  6. 遍历元素:可以使用迭代器(Iterator)增强型for循环for循环遍历ArrayList中的元素。

示例代码

下面是一个简单的示例,展示了如何使用ArrayList:

import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListExample {
    public static void main(String[] args) {
        // 创建一个ArrayList
        ArrayList<String> list = new ArrayList<>();

        // 添加元素
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        // 使用迭代器遍历元素
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }

        // 使用增强型for循环遍历元素
        for (String element : list) {
            System.out.println(element);
        }

		// 使用增强型for循环遍历元素
		for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i)+" ");
        }

        // 修改元素
        list.set(1, "Orange");

        // 删除元素
        list.remove("Banana");

        // 打印ArrayList
        System.out.println(list);
    }
}

迭代器(Iterator)或增强型for循环和for循环遍历效率对比

在这里插入图片描述

  • 通过上图发现,for循环效率最高,增强for循环次之,迭代器最低
  • 这只是元素比较少,元素多的时候会更加明显。

最后

如果感觉有收获的话,点个赞 👍🏻 吧。
❤️❤️❤️本人菜鸟修行期,如有错误,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍在这里插入图片描述

;