Array
最后更新于
Array
是有序的,支持随机读写的集合类型
+
,append(_:)
可以在数组尾部添加元素
insert(_:,at:)
在索引指定的位置插入元素
remove(at:)
删除索引指定位置的元素
removeLast()
删除数组中的最后一项
使用下标法访问Array
中的元素
可以直接使用for-in
循环遍历数组
如果同时需要每个数据项的值和索引值,可以使用 enumerated()
方法来进行数组遍历。enumerated()
返回一个由索引值和数据值组成的元组数组。
如果你试图通过越界索引来执行访问或者修改数据的操作,会引发一个运行时错误。此时可以使用索引值和数组的 count 属性进行比较来在使用该索引之前检验其是否有效。除了当 count 等于 0 时(说明这是个空数组),最大索引值一直是 count - 1,因为数组都是零起索引。
每个数组都会预留一定数量的内存空间去保存元素。当在数组中添加元素且超出预留的数量;数组会申请一块更大的内存空间,并将元素复制到新的内存空间中。
新的内存空间是旧空间的数倍大小。指数级的增长策略意味着多次append操作的平均性能是实时的。触发内存充分配的append 操作有一定的性能消耗,但是数组的容量的逐渐增大,内存分配将会发生的更少。
如果预先知道需要存储的元素数量,可以在添加元素之前调用reserveCapacity(_:)
避免内存重分配。capacity
和 count
属性可以用于计算可用容量。
对于大部分元素类型,存储区域是一个连续的内存空间。对于元素类型是 class 或者 @objc protocol 的数组,存储区域可以是一个连续的内存空间或者NSArray的对象。
Array 是struct类型,也就是值类型。Array对象的每一个拷贝之间都是独立的,修改一个拷贝并不会影响其他拷贝。
如果 Array 的元素类型是值类型,那不仅是Array对象的每个拷贝是独立的,Array对象的每个拷贝对应的元素也是独立的,修改某个拷贝的元素不会影响其他拷贝的对应元素。
如果 Array 的元素类型是引用类型,尽管Array对象的每个拷贝是独立的,Array对象的每个拷贝对应的元素是浅拷贝,指向同一个引用类型对象。
标准库中的许多集合包括Array都使用了 写时拷贝 优化。 Array 的多个拷贝共享同一块存储空间,直到某一个拷贝被修改。
当Array的某个拷贝首次被修改时,会复制出一块新的独属于该拷贝的存储空间,然后再修改;之后再修改就不再有申请新的存储空间的开销了。
当你需要 Array 和 NSArray 对象之间相关转换,可以使用类型声明运算符(as
)来实现桥接。桥接的前提是元素的类型必须是class
或者@objc protocol
或者Foundation类型
。
有以下的示例:
colors
是 Array<String>
的数组,元素类型为 String
, String
是一个Foundation类型,可以桥接;
moreColors
是 Array<String?>
, 元素类型为 String?
, String?
本质上是枚举类型,不是class
或者@objc protocol
或者Foundation类型
中任意一种,因此不可以桥接。
class
或者 @objc protocol
的桥接性能当元素类型为 class
或者 @objc protocol
, Array
桥接为 NSArray
的时间复杂度和空间复杂度都是 O(1)
当元素类型为 class
或者 @objc protocol
, NSArray
桥接为 Array
首先调用 copy(with:)
方法获得一个可变的拷贝数组,然后执行额外的Swift保存操作,将会消耗O(1)的时间复杂度。如果是 NSMutableArray
对象桥接为Array
,copy(with:)
通常会在O(1)时间内返回同一个数组对象,否则copy的性能将是不确定的。如果copy(with:)
返回同一个数组对象,NSArray
和 Array
共享同一块支持写实拷贝的存储空间。
当元素类型为Foundation中的非class类型, Array
桥接为 NSArray
的时间复杂度和空间复杂度都是 O(n)
当元素类型是Foundation中的非class类型,NSArray
桥接为 Array
会在 O(n) 的时间复杂度内将元素拷贝到一块连续存储中。