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 数据结构选型不再纠结!

相关推荐
传奇开心果编程14 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne20 小时前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
大熊猫侯佩2 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
SoaringHeart2 天前
Swift 进阶&封装:仿 Get 给SwiftUI 添加路由导航能力
swiftui·swift
2501_915918413 天前
使用 VS Code 写 Swift 做 iOS 开发,插件能实现哪些功能,还有哪些短板
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
HouWan3 天前
Swift 6.4 发布:iOS开发者值得关注的新特性
ios·swift·apple
00后程序员张4 天前
Xcode vs KXApp,体积差几十G,选轻量方案还是完整工具链?
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子6 天前
iPhone Duo 带来的机遇与挑战 -- 肘子的 Swift 周报 #153
人工智能·swiftui·swift
闲云自留地7 天前
云平台存储管理员:Cinder 创建挂载卷 + Swift 分布式存储原理
分布式·wpf·swift
2501_9159090610 天前
SwiftUI 和 UIKit 怎么选?两代 UI 框架的适用范围
vscode·ios·objective-c·个人开发·swift·敏捷流程