Swift 数据容器全景手册:Sequence、Collection、Set、Dictionary 一次掌握

从协议层设计到实战选型,帮你彻底厘清「什么时候用 Array,什么时候用 Set」。

两个顶层协议:Sequence vs Collection

特性 Sequence Collection
顺序访问 ✅ 单向迭代 ✅ 双向/随机访问
可遍历多次 ❌ 不一定 ✅ 总是
下标访问 ❌ 无 ✅ 有
count 复杂度 O(n) O(1) 或 O(n)

一句话:所有 Collection 都是 Sequence,反之则不成立。

Sequence:只关心「能不能 for-in」

最小实现

swift 复制代码
// 斐波那契作为无限序列
struct Fibonacci: Sequence {
    func makeIterator() -> some IteratorProtocol {
        return FibIterator()
    }
}

struct FibIterator: IteratorProtocol {
    private var a = 0, b = 1
    mutating func next() -> Int? {
        let value = a
        (a, b) = (b, a + b)
        return value
    }
}

// 使用
for (i, v) in Fibonacci().prefix(10).enumerated() {
    print("F[\(i)] = \(v)")
}

延迟特性(Lazy)

swift 复制代码
// 不会立即分配 1_000_000 个元素
let huge = (0..<1_000_000).lazy.map { $0 * $0 }

Collection:在 Sequence 上加「下标」

核心层级

markdown 复制代码
Sequence
 └── Collection
      ├── MutableCollection
      ├── BidirectionalCollection
      └── RandomAccessCollection

自定义 Collection 示例

swift 复制代码
// 只读字符串切片集合
struct SubstringCollection: Collection {
    let base: String
    let substrings: [Substring]

    var startIndex: Int { 0 }
    var endIndex:   Int { substrings.count }
    func index(after i: Int) -> Int { i + 1 }
    subscript(position: Int) -> Substring { substrings[position] }
}

四大常用容器对比

容器 有序? 唯一? 读写 典型场景
Array 随机读写 列表、栈、队列
Set Hash 表 去重、交集、差集
Dictionary Key 唯一 键值映射 缓存、配置
NSOrderedSet 索引+唯一 有序去重(需 Foundation)

Array 深度指南

值语义与写时复制 (CoW)

swift 复制代码
var a = [1, 2, 3]
var b = a           // 共享同一块内存
b.append(4)         // 触发 CoW,复制一份

性能陷阱:大数组拷贝

swift 复制代码
// 避免在 for 循环中直接 append
let squared = largeArray.map { $0 * $0 }   // 一次分配

Set:哈希与唯一性的艺术

基本操作

swift 复制代码
let odd: Set = [1, 3, 5]
let even: Set = [2, 4, 6]
print(odd.union(even))            // [1, 2, 3, 4, 5, 6]
print(odd.intersection(even))     // []

自定义可哈希类型

swift 复制代码
struct Point: Hashable {
    let x, y: Int
    // 自动合成 Hashable
}

let points: Set<Point> = [Point(x: 1, y: 2), Point(x: 3, y: 4)]

Dictionary:字典的正确打开方式

分组 & 计数

swift 复制代码
let words = ["apple", "banana", "apricot"]
let grouped = Dictionary(grouping: words, by: { $0.first! })
// ["a": ["apple", "apricot"], "b": ["banana"]]

let counts = Dictionary(words.map { ($0, 1) }, uniquingKeysWith: +)

嵌套字典优雅读写

swift 复制代码
extension Dictionary where Key == String, Value == Any {
    subscript(path path: String) -> Any? {
        get {
            var keys = path.split(separator: ".").map(String.init)
            return keys.reduce(self) { ($0 as? [String: Any])?[$1] }
        }
    }
}

let dict = ["user": ["profile": ["name": "Ada"]]]
print(dict[path: "user.profile.name"] ?? "N/A") // "Ada"

选型决策树

javascript 复制代码
需要下标随机访问?
├─ 是 → Collection
│   ├─ 需要唯一性 → Set / Dictionary
│   └─ 需要顺序   → Array
└─ 否 → Sequence(延迟计算,节省内存)

性能速查表

操作 Array Set Dictionary
append/insert O(1) amortized O(1) O(1)
contains O(n) O(1) O(1)
remove O(n) O(1) O(1)
sort O(n log n) ❌ 无序 ❌ 无序

实战 Checklist

  1. 列表渲染 → Array
  2. 搜索去重 → Set
  3. 键值缓存 → Dictionary
  4. 大数据链式处理 → .lazy Sequence
  5. 需要有序去重 → NSOrderedSet(Foundation)

一句话总结

顺序访问用 Array,唯一性用 Set,键值映射用 Dictionary,延迟计算用 Sequence。

牢记这句口诀,Swift 数据结构选型不再纠结!

相关推荐
njsgcs1 天前
Swift playground 网页刷新切换随机页面的网页查看器WebKit
swift
桃子叔叔3 天前
基于SWIFT框架的预训练微调和推理实战指南之完整实战项目
大模型·swift
菜的不敢吱声3 天前
swift学习第5天
学习·ssh·swift
符哥20083 天前
Swift开发app常见第三方库
学习·swift
初级代码游戏4 天前
iOS开发 SwiftUI 5 : 文本输入 密码输入 多行输入
ios·swiftui·swift
菜的不敢吱声4 天前
swift学习第4天
服务器·学习·swift
菜的不敢吱声5 天前
swift学习第2,3天
python·学习·swift
大熊猫侯佩6 天前
拒绝“假死”:为何上滑关闭是测试大忌?揭秘 iOS 真实 OOM 触发指南
app·swift·apple
大熊猫侯佩6 天前
Swift 6.2 列传(第十六篇):阿朱的“易容术”与阿紫的“毒药测试”
swift·编程语言·apple
麦兜*6 天前
【Swift】苹果App开发全流程解析:从Xcode配置到App Store上架避坑指南
xcode·swift