首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【重学数据结构】数组 ArrayList

【重学数据结构】数组 ArrayList

作者头像
程序员三明治
发布2025-12-18 20:02:11
发布2025-12-18 20:02:11
1320
举报
文章被收录于专栏:码力up码力up

数组是什么?

数组是一种线性表的数据结构,是一个存储相同数据类型的集合,每个相邻元素的物理内存地址也相邻。

实现一个ArrayList

内部属性

代码语言:javascript
复制
    // 默认的初始化空间
    private static final int DEFAULT_CAPACITY = 10;
    // 默认的空元素数组
    private static final Object[] DEFAULT_EMPTY_ELEMENTDATA = {};
    // 元素数组缓冲区
    private Object[] elementData;
    // 元素个数
    private int size;

在我们初始化ArrayList的时候,如果指定了容量大小的话,那它就会创建一个指定容量大小的数组;如果没指定,默认会初始化一个空的数组,等add第一个元素的时候,容量扩充为10。 

添加元素

代码语言:javascript
复制
    @Override
    public boolean add(E e) {
        // 确保最小容量
        int minCapacity = size + 1;
        if (elementData == DEFAULT_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 判断扩容操作
        if (minCapacity > elementData.length) {
            int oldCapacity = elementData.length;
            // 扩容1.5倍
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            // 例如添加单个元素但当前容量为 0,则直接使用minCapacity
            if (newCapacity < minCapacity) {
                newCapacity = minCapacity;
            }
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
        // 添加元素
        elementData[size++] = e;
        return true;
    }
  1. 判断当前容量与初始化容量,使用 Math.max 函数取最大值最为最小初始化空间。
  2. 接下来是判断 minCapacity 和元素的数量,是否达到了扩容。首次创建 ArrayList 是一定会扩容的,也就是初始化 DEFAULT_CAPACITY = 10 的容量。
  3. Arrays.copyOf 实际上是创建一个新的空间数组,之后调用的 System.arraycopy 迁移到新创建的数组上。这样后续所有的扩容操作,也就都保持统一了。
  4. 使用 elementData[size++] = e添加元素 

删除元素 

代码语言:javascript
复制
    public E remove(int index) {
        E oldValue = (E) elementData[index];
        int numMoved = size - index - 1;
        if (numMoved > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        }
        elementData[--size] = null;
        return oldValue;
    }
  1. 首先需要计算出删除此元素所要移动的元素数,也就是numMoved
  2. 使用System.arraycopy拷贝数据的方式去移动数据,把删除掉的元素的位置覆盖掉
  3. 然后把末尾的数据(移动后为脏数据)置为null 

获取元素

代码语言:javascript
复制
    @Override
    public E get(int index) {
        return (E) elementData[index];
    }

    @Override
    public String toString() {
        return "ArrayList{" +
                "elementData=" + Arrays.toString(elementData) +
                ", size=" + size +
                '}';
    }

自测 

代码语言:javascript
复制
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        list.add("01");
        list.add("02");
        list.add("03");
        list.add("04");
        list.add("05");
        list.add("06");
        list.add("07");
        list.add("08");
        list.add("09");
        list.add("10");
        list.add("11");
        list.add("12");

        System.out.println(list);

        list.remove(9);

        System.out.println(list);
    }

 测试结果

image.png
image.png

常见问题 

数据结构中有哪些是线性表数据结构? 

数组、链表、栈、队列

数组的元素删除和获取,时间复杂度是多少?

删除元素是On,因为删除元素后,需要移动其他元素 获取元素是O1 

ArrayList 中默认的初始化长度是多少?

ArrayList在首次添加元素之前,底层数组是一个空数组,在首次添加元素的时候自动扩容到10。

ArrayList 中扩容的范围是多大一次?

扩容是按原容量的1.5倍去扩容

ArrayList 是如何完成扩容的,System.arraycopy 各个入参的作用是什么?

完成扩容的步骤:

  1. 判断当前容量与初始化容量,如果第一次add元素则Math.max取最大值给minCapacity
  2. 判断 minCapacity 和元素的数量,是否达到了扩容,然后使用Arrays.copyOf进行数组的拷贝并扩容
  3. 添加元素

System.arraycopy(旧数组,旧数组的起始下标,新数组,新数组的起始下标,迁移的数据量) 

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数组是什么?
  • 实现一个ArrayList
    • 内部属性
    • 添加元素
    • 删除元素 
    • 获取元素
  • 自测 
  • 常见问题 
    • 数据结构中有哪些是线性表数据结构? 
    • 数组的元素删除和获取,时间复杂度是多少?
    • ArrayList 中默认的初始化长度是多少?
    • ArrayList 中扩容的范围是多大一次?
    • ArrayList 是如何完成扩容的,System.arraycopy 各个入参的作用是什么?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档