从0开始手写ArrayList动态数组

Posted 小胖java攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从0开始手写ArrayList动态数组相关的知识,希望对你有一定的参考价值。

源代码码云Gitee下载链接

在这里插入图片描述

1.什么是数组?

在了解什么是数组之前,我们先了解什么是线性表,线性表是具有 n 个相同类型元素的有限序列,数组就是一种线性的数据结构,是一种顺序存储的线性表,所有元素的内存地址是连续的
在这里插入图片描述

2.为什么数组查询效率这么快?

处理速度由快到慢排序:
1、CPU寄存器 2、CPUL1缓存 3、CPUL2缓存 4、内存 5、硬盘

因为CPU缓存会读入一段连续的内存,顺序存储符合连续的内存,所以顺序存储可以被缓存处理,而链接存储并不是连续的,分散在堆中,所以只能内存去处理。

第一:Java的数组中存储的每个元素类型一致,也就是说每个元素占用的空间大小相同。

第二:Java的数组中存储的每个元素在空间存储上,内存地址是连续状态的。

第三:通常首元素的内存地址作为整个数组对象的内存地址,可见我们是知道首元素内存地址的。

第四:再加上数组中的元素是有下标的,有下标就可以计算出被查找的元素和首元素的偏移量。

综上所述,实际上在数组中查找元素是可以通过数学表达式计算被查找元素的内存地址的,通过内存地址可以直接定位该元素。也就是说数组中有100个元素和有100万个元素,实际上在查找方面效率是一样的。

3.什么是动态数组?

由于数组有一个缺点就是大小是固定的,这时候我们需要引入可以对数组容量扩容和缩容的操作,所以这类数组称之为动态数组。

4.动态数组存基本类型和对象(引用)类型有什么区别?

  • 基本类型动态数组存储的是数据

  • 对象类型动态数组存储的是对象的内存地址

    以下是动态数组存储对象类型的示例图
    在这里插入图片描述

5.接口设计

  • int size(); // 元素的数量
  • boolean isEmpty(); // 是否为空
  • boolean contains(E element); // 是否包含某个元素
  • void add(E element); // 添加元素到最后面
  • E get(int index); // 返回index位置对应的元素
  • E set(int index, E element); // 设置index位置的元素
  • void add(int index, E element); // 往index位置添加元素
  • E remove(int index); // 删除index位置对应的元素
  • int indexOf(E element); // 查看元素的位置
  • void clear(); // 清除所有元素

6.代码实现重点和难点讲解

添加 add(int index, E element)

/**
  * 在index位置插入一个元素
  */
public void add(int index, E element) {
   //检查下标正确性
   rangeCheckForAdd(index);
   //是否需要扩容
   ensureCapacity(size + 1);
   //从左往右挪动
   for (int i = size; i > index; i--) {
      elements[i] = elements[i - 1];
   }
   elements[index] = element;
   size++;
}

这个从左往右挪动是什么意思?

假设存在数组array。

在这里插入图片描述

假设我们要想在 3 位置添加元素 88 ,那么按照我的代码逻辑,从左往右挪动的意思是,从66开始移动,左边的下标为 566 移动到右边的下标为 6 的位置,以此类推。
在这里插入图片描述
绿色是移动的顺序,那么紫色部分就是待添加元素 88 添加的位置。
在这里插入图片描述

大功告成!!!

删除 E remove(int index)

/**
 * 删除index位置的元素
 * @return 被删除的元素
 */
public E remove(int index) {
   //检查下标正确性
   rangeCheck(index);
   
   E old = elements[index];
   //从右往左挪动
   for (int i = index + 1; i < size; i++) {
      elements[i - 1] = elements[i];
   }
   elements[--size] = null;
   //是否需要缩容
   trim();
 
   return old;
}

假设存在数组array
在这里插入图片描述
假设我们想删除下标为 2 的元素 33 ,从右往左挪动的意思是,从44开始移动,右边的下标为 344 移动到左边的下标为 2 的位置,以此类推。

在这里插入图片描述
红色是移动的顺序,那么黑色部分就是待元素变为 null 位置。
在这里插入图片描述

大功告成!!!

我是小胖,越努力越幸运

在这里插入图片描述

以上是关于从0开始手写ArrayList动态数组的主要内容,如果未能解决你的问题,请参考以下文章

从0开始手写ArrayList动态数组和LinkedList双向链表

恋上数据结构手写ArrayList + Java动态扩容分析

利用Java来手写ArrayList

利用Java来手写ArrayList

从 0 开始手写一个 Mybatis 框架,三步搞定!

C#中的ArrayList