当前位置:网站首页>数组初相识

数组初相识

2020-11-08 18:59:59 Java小舍

什么是数组

​ 看到这个问题时,想必答案已经在你脑中了吧.通俗的来说: 数组是用一组连续的内存空间,来存储一组具有相同类型的数据。 也可以说数组的作用是将相同类型的数据,存储在一组连续的内存空间中.

连续的内存空间:关键字连续,为什么需要连续的内存空间呢,难道不连续不可以吗?

​ 根据《Java虚拟机规范》的规定,Java堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的,这点就像我们用磁盘空间去存储文件一样,并不要求每个文件都连续存放。但对于大对象(典型的如数组对象),多数虚拟机实现出于实现简单、存储高效的考虑,很可能会要求连续的内存空间。

   正是因为连续的内存空间和相同类型的数据,才使得数据具有随机访问的特性,然而成也风云,败也风云.因为"风云"使得数据的很多操作都变得低效,例如对数据执行删除或插入操作时,为了保证连续性,就需要做大量的搬移工作.

如何创建

Java 中,使用[]来定义一个数组.常见的创建方式有以下三种

//1)使用长度定义数组
int[] arr = new int[3];

//2)使用数据直接定义数组
int[] arr = new int[]{1,2,3};

//3)使用数据直接定义
int[] arr = {1,2,3};

注意:数组一旦被定义,其长度便无法更改,如果需要更改,可定义一个新的数据,将原有数据copy过去即可

不同的数据类型在内存中存储的方式不同

  • int、long、char等基本数据类型的数据

new申请的空间在堆上,arr存储在栈上。arr存储的是数组空间的首地址。

从图中来看,在Java中,基本数据类型数组还是符合数据结构中数组的定义的。数组中数据是相同类型的、并且存储在一片连续的内存空间中。

  • 存储对象类型的数据

在Java中,对象数组中存储的是对象在内存中的地址,而非对象本身。对象本身在内存中并不是连续存储的,而是散落在各个地方的。

如何使用

赋值

int[] arr = new int[3];
arr[2] = 3;//给下标为2赋值为 3

arr[2] = 6;//如果再次赋值,原来的数据将被覆盖

插入

  1. 新建数组,对原数组扩容
  2. 将原数组数据赋值给新数组
  3. 将大于i的数据向后移动一位
  4. 赋值到k位置

如果数组只是作为一个存储功能的容器且里面的数据元素是无序的;为了避免大规模的数据搬移,可以直接将第 k 位的数据搬移到数组元素的最后,把新的元素直接放入第 k 个位置,反之只能采取移动数据元素的方式。

删除

跟插入数据的操作类似,为了内存的连续性,也需要搬移数据。

如果要删除多个数据时,难道我们每次删除都要进行数据搬移吗?就好比在生活中,当我们有想要扔掉的东西时,每次我们都会把东西拿出去吗?当然不是,实际上我们只是将它放到了垃圾通里面,而此时并没有消失,只是被"标记"成了垃圾。只有垃圾桶满了,才会清理垃圾桶。

我们可以利用这种思想,当要删除多个数据时,先将其"标记"(扔到垃圾桶),当标记完成后(垃圾桶满了),在执行删除操作,进行数据搬移(清理垃圾桶)。

有的舍友可能会说:"把东西扔到垃圾桶,那不是移动了位置吗?"

可以这样里理解:将东西扔到垃圾桶只是"标记"的一种实现方式,例如我们还可以在要扔弃的东西上写上"这是个垃圾".

熟悉JVM的舍友,可能会发现这不正是标记清除垃圾回收算法的思想吗?

JVM标记清除算法:

大多数主流虚拟机采用可达性分析算法来判断对象是否存活,在标记阶段,会遍历所有 GC ROOTS,将所有 GC ROOTS 可达的对象标记为存活。只有当标记工作完成后,清理工作才会开始。具体的内容后面会有专门文章介绍.

索引越界

创建数组时,就已经指定了数组长度.假如数组长度为k,数组的索引值是从0开始,那么索引的范围为 0--(k-1),

int[] arr = new int[3];
arr[3] = 6;//会抛出 java.lang.ArrayIndexOutOfBoundsException

应用场景

  1. 在平常的开发中大多数都是做业务开发,我们直接使用容器就足够了,因为它将对数据的的操作细节进行封装,使用起来非常方便.如果对性能要求很高的话,那么优先使用数组
  2. 开发中,如果已知数据大小,且没有复杂操作,那么也可以直接使用数组.

版权声明
本文为[Java小舍]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/JavaUrl/p/13945235.html