Swift如何在内部管理阵列?

我想知道Swift如何在内部管理数组? Apple’s language guide仅处理使用情况,但没有详细说明内部结构.

作为一名Java开发人员,我习惯将“裸”数组视为非常静态和固定的数据结构.我知道Swift不是这样.在Swift中,除了Java之外,您可以改变数组的长度并执行插入和删除操作.在Java中,我习惯于根据我想用该结构执行的操作来决定我想要使用的数据结构(简单数组,ArrayList,LinkedList等),从而优化我的代码以获得更好的性能.

总之,我想知道如何在Swift中实现数组.它们是内部管理的(双)链表吗?是否有可与Java的Collection Framework相媲美的东西,以便调整以获得更好的性能

您可以在Swift标准库的上面的注释中找到有关Array的大量信息.要查看此内容,您可以在操场上cmd-opt-click Array,或者您可以在非官方的 SwiftDoc页面中查看它.

从那里解释一些信息来回答你的问题:

在Swift中创建的数组将其值保存在连续的内存区域中.因此,您可以有效地将Swift数组传递到需要这种结构的C API.

正如您所提到的,当您向其附加值时,数组可以增长,并且在某些点处,这意味着分配了一个更大的新内存区域,并将先前的值复制到其中.正是出于这个原因,它声明像append这样的操作可能是O(n) – 也就是说,执行追加操作的最坏情况时间与数组的当前大小成比例增长(因为复制所花费的时间)价值超过).

但是,当阵列必须增加其存储空间时,它每次分配的新存储量会呈指数级增长,这意味着重新分配会随着您的追加而变得越来越罕见,这意味着在所有调用上追加的“分摊”时间接近恒定时间.

数组也有一个方法,reserveCapacity,它允许你通过请求数组预先为自己分配一些最小量的空间来预先避免重新分配调用append.如果您提前知道计划在阵列中保留多少个值,则可以使用此方法.

在数组的中间插入一个新值也是O(n),因为数组保存在连续的内存中,因此插入一个新值需要将后续值混合到最后.与附加不同,这不会改善多个呼叫.这与链接列表非常不同,您可以在其中插入O(1)即恒定时间.但请记住,最大的权衡是,与链接列表不同,数组也可以在不变的时间内随机访问.

对数组中单个值的原位更改(即通过下标分配)应为O(1)(下标实际上没有记录注释,但这是一个非常安全的选择).这意味着如果您创建一个数组,填充它,然后不附加或插入它,它在性能方面应该与Java数组类似.

所有这一点都有一点需要注意 – 数组具有“价值”语义.这意味着如果你有一个数组变量a,并将它分配给另一个数组变量b,这实质上是复制数组. a中值的后续更改不会影响b,更改b不会影响a.这与“引用”语义不同,其中a和b都指向同一个数组,并且通过a对其进行的任何更改都会反映给通过b查看它的人.

但是,Swift数组实际上是“copy-on-Write”.也就是说,当您指定a到b时,实际上不会进行复制.只有当两个变量中的一个发生变化(“变异”)时才会发生.这带来了很大的性能优势,但它确实意味着如果两个数组引用相同的存储,因为自复制以来都没有执行写操作,像下标分配这样的更改确实会在此处重复整个数组的一次性成本点.

在大多数情况下,除了在极少数情况下(特别是在处理小到中等大小的数组时),你不应该担心这些,但如果性能对你很重要,那么绝对值得你熟悉所有的该链接中的文档.

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...