swift 基础:探究 Array 和 Set 的区别

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

数组(Array)和集合(Set)都是集合类型,并且有很多相似之处,但是有意思的是在日常开发中我们通常使用数组,而不是集合。

在面试中,也经常被问到两者的异同,今天来讲讲这两个类型的区别。

相同点

1、相同的初始化语法糖

初始化一个 Array 和初始化一个 Set 都可以直接通过中括号 [] 进行:

sql 复制代码
let array: Array<Int> = [1, 2, 3, 4, 5]
let set: Set<Int> = [1, 2, 3, 4, 5]

这是因为它们都实现了 ExpressibleByArrayLiteral 协议,如果不声明类型为 Set<Int>,默认情况下它将生成一个数组。

2、都是值类型

数组和集合都是值类型。如果使用 let 定义 Set,那么当使用 insert 函数尝试添加对象时,将遇到以下错误:

不同点

1、添加对象的方式不同

往数组里添加对象使用 append 函数我们已经很熟悉了,但是往集合里添加函数需要用到 insert 这个函数:

swift 复制代码
func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element)

从这个函数定义上可以看出,它返回一个元组类型,inserted 代表是否插入成功,memberAfterInsert 代表插入的这个元素,可以通过这个函数轻易判断是否存在相同的元素:

swift 复制代码
var set: Set<Int> = [1, 2, 3, 4, 5]
let (inserted, memberAfterInsert) = set.insert(2)
if inserted {
    print("\(memberAfterInsert) 插入成功!")
} else {
    print("集合中已经存在元素 \(memberAfterInsert),插入失败!")
}

2、Set 中的元素不能重复

这是集合和数组之间的一个最大的区别,元素的唯一性。数组可以包含多个相同的值,而集合永远不会包含重复项。这也是上面的 insert(_:) 方法返回一个布尔值来表示插入是否真正成功的原因。

正因为这个特性,集合也经常用来为数组做去重操作

3、元素的顺序不同

数组会保证元素的顺序,先 append 的在前面,后 append 的在后面,也可以通过 insert(_: at:) 方法来把元素插入到固定的位置。

但是 Set 是一个 无序集合,不保证元素的位置。

sql 复制代码
var array: Array<Int> = [1, 2, 3, 4, 5]
var set: Set<Int> = [1, 2, 3, 4, 5]
print(array, set)

上边的代码打印:[1, 2, 3, 4, 5] [4, 2, 5, 3, 1],不管运行多少次,array 的元素顺序总是固定的,而 Set 的元素可能每次执行的结果都不一样。

因此,如果元素的顺序对你的需求很重要,你应该选择数组。

4、子元素类型略有不同

ArraySet 的子元素类型都是范型,但是 Set 要求子元素必须实现 Hashable 协议(可哈希),而 Array 对子元素没有要求。

标准库中的大多数类型(字符串、数字、Bool)都是可哈希的。

但如果是自定义的类型,就需要先遵守 Hashable 协议才能存进 Set 中,Set 底层也是根据 Hashable 中的 hashValue 值来去重的。

性能方面比较

ArraySet 在 Swift 中都是通过泛型和协议来实现的。

在底层,Array 使用连续内存存储元素,这也保证了它的元素顺序是固定的。连续的内存空间也使得访问元素时速度快,但插入和删除元素可能需要移动其他元素,导致性能下降。

Set 则使用哈希表进行存储(跟字典原理相同),存储的内存是不连续的,哈希表好处是查找、添加、删除操作速度都很快(平均时间复杂度为O(1)),但坏处是会消耗更多内存。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
开心就好202520 分钟前
Flutter iOS应用混淆与安全配置详细文档指南
后端·ios
mCell2 小时前
MacOS 下实现 AI 操控电脑(Computer Use)的思考
macos·agent·swift
开心就好20252 小时前
苹果iOS应用开发上架与推广完整教程
后端·ios
用户69371750013842 小时前
XChat 为什么选择 Rust 语言开发
android·前端·ios
MonkeyKing2 小时前
Objective-C Runtime 完整机制:objc_class /cache/bits 源码解析
前端·ios
用户79457223954132 小时前
【DGCharts】iOS 图表渲染事实标准——8 种图表类型、高度可定制,3 行代码画出一条折线
swiftui·swift
秋雨梧桐叶落莳4 小时前
【iOS】 AutoLayout初步学习
学习·macos·ios·objective-c·cocoa·xcode
chaoguo123414 小时前
Any metadata 的内存布局
swift·metadata·value witness table
SY.ZHOU1 天前
移动端架构体系(四):View层的组织与调用方案
flutter·ios·架构·系统架构·安卓
inxx1 天前
iOS 26 模拟器启动卡死:Method Swizzling 在系统回调时触发 nil 崩溃
ios