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

相关推荐
HarderCoder5 小时前
深入理解 SOLID 原则:用 Swift 编写优雅、可维护的代码
swift
HarderCoder5 小时前
Swift 并发全景指南:Thread、Concurrency、Parallelism 一次搞懂
swift
HarderCoder6 小时前
Swift 并发模型深度解析:Singleton 与 Global Actor 如何抉择?
swift
HarderCoder9 小时前
Swift Global Actor 完全指南
swift
HarderCoder9 小时前
Swift 计算属性(Computed Property)详解:原理、性能与实战
swift
HarderCoder9 小时前
Swift Property Wrapper:优雅地消除样板代码
swift
东坡肘子11 小时前
未来将至:人形机器人运动会 | 肘子的 Swift 周报 #099
swiftui·swift·apple
大熊猫侯佩1 天前
反抗军工程师的 “苹果智能” 实战指南:用本机基础模型打造 AI 利刃
ai编程·swift·apple
YungFan2 天前
iOS26适配指南之UIViewController
ios·swift