【Java -- 数据结构】什么是数组(Array)?

前言

数组是一种大小固定的数据结构,对线性表的所有操作都可以通过数组来实现。数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。虽然数组一旦创建之后,它的大小就无法改变了,但是当数组不能再存储线性表中的新元素时,我们可以创建一个新的大的数组来替换当前数组。这样就可以使用数组实现动态的数据结构。

优点:

  • 可以通过下标来访问或者修改元素,比较高效

缺点:

  • 增删慢,插入和删除的花费开销比较大,比如当在第一个位置前插入一个元素,那么首先要把所有的元素往后移动一个位置
  • 大小固定,只能存储单一元素。

数组是如何根据下标实现随机访问的?

比如一个长度为10 的 int 类型的数组:

int[] arr = new int[10];

在这里插入图片描述
从图中可以看到,计算机给数组a分配了一块连续的内存1000-1039.其中内存块的首地址为base_address=1000。

我们知道计算机会给每一个内存单元分配一个地址,计算机通过地址来访问内存中的数据。当计算机要访问数组中的某个元素的时候就会通过下面公式寻找地址:

a[i]_address = base_address + i*data_type_size

这里的 data_type_size 表示数组中每个元素的大小,因为例子中是 int 所以大小为 4 。

为什么数组的插入和删除是低效的?

  • 插入操作
    假如数组的长度为n,如果我们需要将一个数据插入到数组中的第k个位置,为了把第k个位置腾出来,需要把第k~n这部分的元素都顺序的往后挪一位,操作复杂。
    如果在数组的末尾插入元素,那就不需要移动数据了,插入比较简单,单是如果在数组的头部插入元素就复杂了,需要把所有的数据都往后移动一位。
    如果一个数组中的数据是有序的,那我们在某一个位置插入一个新的元素的时候就必须得按照上面的方法移动k之后的数据,但是数组中存储的数据如果没有任何规律,这时候,如果想要把某个元素插入到k位置,为了避免大规模的数据搬移,有个简单的办法就是:直接把k位置的数据搬到数组的最后面,把新元素放到第k个位置。

  • 删除操作:
    跟插入数据类似,如果我们要删除第k个位置的数据,为了内存的连续性,也需要搬移数据,不然中间就会出现空洞。
    在某些情况下,如果我们不要求数据必须是连续的,那么删除的时候可以不真删除,只是把这个元素标记为已删除,当组空间不够用的时候,在触发一次真正的删除,这样就大大减少了删除操作导致的搬移操作。
    其实JVM的核心垃圾算法就是这个思想。

ArrayList

java 中的 ArrayList 相当与一个动态数组,支持扩容。它可以把很多数组操作的细节封装起来,比如数组的插入和删除。

数组在定义的时候,因为需要给它分配连续的内存空间,需要预先指定其大小,当存放的数据大于其大小的时候,我们需要从新分配一块更大的空间,把原来的复制过去在插入新的元素。

ArrayList 中,当空间不够用的时候,它会自动扩容为原来的 1.5 倍的大小。

因为扩容设计到内存的申请和数据的搬移,这是比较耗时的,所以,如果事先能确定数据的大小,做好在创建 ArrayList 的时候指定其大小

虽然 ArrayList 比数组好用,不过有些时候使用数组会更好一些。

1)因为 ArrayList 无法存储基本类型,int long 等需要封装成 Integer,Long 类,而自动装箱和拆箱的操作也会有一定的性能消耗,所以如果关注性能或者想用基本类型就选用数组

2)如果数据的大小已经知道,并且对数据的操作简单,可以直接使用数组

3)当使用多为数组的时候,用数组表示起来更加直观比如 int[][]arr ;而用容器的话则需要这样定义ArrayList arr。

在开发中,一般情况下直接使用ArrayList就可以,如果是偏底层的开发比如网络框架开发等需要更高的性能,使用数组更合适。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin-Dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值