likes
comments
collection
share

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

作者站长头像
站长
· 阅读数 49

《Java零基础教学》是一套深入浅出的 Java 编程入门教程。全套教程从Java基础语法开始,适合初学者快速入门,同时也从实例的角度进行了深入浅出的讲解,让初学者能够更好地理解Java编程思想和应用。

本教程内容包括数据类型与运算、流程控制、数组、函数、面向对象基础、字符串、集合、异常处理、IO 流及多线程等 Java 编程基础知识,并提供丰富的实例和练习,帮助读者巩固所学知识。本教程不仅适合初学者学习,也适合已经掌握一定 Java 基础的读者进行查漏补缺。

前言

在Java语言中,数组的大小是在创建时就已经确定的,而且一旦确定之后也不能再次改变。为了弥补这个不足,Java提供了ArrayList类,它封装了一个动态的可增长的对象数组。ArrayList比数组具有更大的灵活性和更方便的方法。本文将对ArrayList的原理与使用进行详细介绍。

摘要

本文将介绍以下内容:

  • ArrayList是什么,它有哪些特点;
  • ArrayList的源码实现与详细解析;
  • ArrayList的常用方法介绍;
  • ArrayList的测试用例;
  • 全文小结。

ArrayList是什么?

ArrayList是Java中最常用的动态数组。它是List接口的一个实现,可以自动扩容,支持增删改查操作。与数组相比,ArrayList有以下几个优势:

  • 可以自动扩容,动态添加元素;
  • 方便进行元素的增删改查操作;
  • 支持泛型,用于存储任意类型的对象。

ArrayList源码实现与详解

ArrayList结构

在Java中,ArrayList实际上是封装了一个数组。这个数组通过构造函数传入一个初始化的容量大小,可以随着元素的增加自动扩容。

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    //默认初始化容量大小
    private static final int DEFAULT_CAPACITY = 10;
    //存储元素的数组
    transient Object[] elementData;
    //数组中元素个数
    private int size;
    //...
}

java.util.ArrayList 源码页截图如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

ArrayList的扩容机制

ArrayList的扩容机制是在添加元素时才进行的。当ArrayList中的元素个数达到容量大小时,会自动扩容。实际上扩容的方法是通过创建一个新的数组,然后将原来的元素全部复制到新的数组中,最后将新的数组替代旧的数组。

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //每次扩容为原来的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //如果扩容后的容量比Integer.MAX_VALUE还大,就使用最大值作为容量
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

java.util.ArrayList 扩容机制源码如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

ArrayList的常用方法介绍

ArrayList类提供了丰富的方法,包括添加、删除、修改、查询等。下面是一些常用的方法介绍。

添加元素

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}

删除元素

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}

修改元素

public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

查询元素

public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

ArrayList的测试用例

如下我带着大家分别写个测试用例尝试一下,演示如下:

新增元素

    //新增元素
    @Test
    public void testAdd() {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        System.out.println(list);
        assertEquals(3, list.size());
    }

测试用例执行如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

删除元素

    //删除元素
    @Test
    public void testRemove() {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");
        System.out.println("删除前:" + list);
        list.remove("Python");
        System.out.println("删除后:" + list);
        assertEquals(2, list.size());
    }

测试用例执行如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

更新元素

    //更新元素
    @Test
    public void testSet() {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        System.out.println("更新前:" + list);
        list.set(1, "C++");
        System.out.println("更新后:" + list);
        assertEquals("C++", list.get(1));
    }

测试用例执行如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

根据下标查询元素

    @Test
    public void testGet() {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        assertEquals("Java", list.get(0));
        assertEquals("Python", list.get(1));
    }

测试用例执行如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

根据元素查找下标

    // 根据元素查找下标
    @Test
    public void testIndexOf() {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        System.out.println("list.indexOf(\"Java\") = " + list.indexOf("Java"));
        System.out.println("list.indexOf(\"Python\") = " + list.indexOf("Python"));
        assertEquals(0, list.indexOf("Java"));
        assertEquals(1, list.indexOf("Python"));
    }

测试用例执行如下:

Java中的ArrayList:Java中最常用的动态数组,你了解多少?

全文小结

本文对ArrayList的定义、源码实现及常用方法进行了详细的介绍。通过本文的学习,我们可以清楚地了解ArrayList的结构,掌握它的扩容机制以及使用方法。ArrayList是Java中最常用的集合类之一,掌握好它的使用方法对于在Java开发中提高效率具有重要意义。

最后

大家如果觉得看了本文有帮助的话,麻烦给个三连(点赞、分享、转发)支持一下哈。

转载自:https://juejin.cn/post/7276630249546907687
评论
请登录