2024-08-13 10:19:03
,某些文章具有时效性,若有错误或已失效,请在下方留言。代码内有什么?
在 swift
标准库文件 Array.swift
中,可以检索到 insert()
方法,如下所示:
public mutating func insert(_ newElement: __owned Element, at i: Int) {
_checkIndex(i)
self.replaceSubrange(i..<i, with: CollectionOfOne(newElement))
}
内部的_checkIndex(i)
方法用来校验插入的位置是否有效,比如插入的位置是-1
。
但另一行代码更有趣:它用一个 CollectionOfOne
对象替换了一个子范围,其中包含了我们要插入的元素。这是一个非常有趣的类型,因为它听起来完全自相矛盾:集合将大量对象存储在一个地方,那么我们为什么要使用一个对象的集合呢?
创建单对象集合
因为 CollectionOfOne
也是一个集合,就像数组和集合一样,我们可以用同样的方法使用它。我们可以创建一个有起始值的集合:
var luckyNumbers = CollectionOfOne(13)
我们可以打印集合的 count
print(luckyNumbers.count) // 1
我们可以遍历集合中的项目
for luckyNumber in luckyNumbers {
print(luckyNumber) // 13
}
我们可以通过他们的位置读取并改变值,位置始终为 0。
print(luckyNumbers[0]) // 13
luckyNumbers[0] = 7
print(luckyNumbers[0]) // 7
我们可以访问像 first
和 last
这样的通用属性。
print(luckyNumbers.first == luckyNumbers.last) // true
…尽管在这种情况下,Swift 的规则意味着 first
和 last
必须是可选的,尽管它们总是存在的。对于通常适用于可能为空的集合的任何属性和方法(例如读取随机值)来说,情况也是如此:
print(luckyNumbers.randomElement()!)
我们无法使用一系列方法来调整集合的大小,比如这些方法:
luckyNumbers.removeAll()
luckyNumbers.append(13)
luckyNumbers.insert(556, at: 0)
因此,这确实是 一个完全由一个元素组成的集合,但为什么需要它–它有什么用处,Swift 本身为什么要使用它?
理解要点
CollectionOfOne
存在的原因有两个:一致性和性能。
一致性就是让代码符合某种形状。例如,我们可能有一个处理任何类型集合的函数,就像这样。
func printItems(in collection: any Collection) {
for item in collection {
print(item)
}
}
我们已经可以传递一个数组或者集合,但是我们不能传递一个单独的项目。如果没有 CollectionOfOne
,我们就不能这样做,因为 CollectionOfOne
就是一个集合,所以这种代码是完全有效的:
printItems(in: luckyNumbers)
这就引出了 CollectionOfOne
的第二个用途,即性能。与其传入一个单元素集合,我们完全可以这样写:
printItems(in: [7])
那我们为什么不这样做呢?至少在很多时候是这样的。然而,使用大小灵活的数组会产生超出所需的开销,因为我们知道我们总是只有一个项目。相反,使用 CollectionOfOne
只比直接传入整数稍慢一些,因为它只是对值进行了很薄的封装,就像 Optional
一样。
这种情况实际上比你想象的还要常见。例如,假设您有一个电影演员数组:
let cast = ["Stewart", "Frakes", "McFadden"]
然后多出一个人扮演角色:
let additional = "Sirtis"
如何将这两个数组组合起来创建一个新数组呢?有了 CollectionOfOne
,答案很简单:
let finalCast = cast + CollectionOfOne(additional)
不仅如此,它的性能也很好,因为 “集合 “只是对值本身的一个薄如刀片的封装,其所有内部结构的实现都非常简单,以至于 Swift 会将它们内联以获得最快的速度。
所以,这就是 CollectionOfOne
:你可能不经常用到它,但至少如果你在其他地方见过,你就会知道为什么会有它!
参考
- 文章来自: Hacking With Swift Plus ↩
暂无评论内容