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新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
RickeyBoy17 小时前
解决 Swift Testing 中 DI 容器的竞态条件
ios
2501_9159184119 小时前
苹果App Store上架审核卡住原因分析与解决方案指南
android·ios·小程序·https·uni-app·iphone·webview
开心就好202520 小时前
不依赖 Mac 也能做 iOS 开发?跨设备开发流程
后端·ios
开心就好202521 小时前
Windows 上传 IPA 到 App Store 的步骤讲解
后端·ios
for_ever_love__1 天前
Objective- C学习: 手动内存管理
c语言·学习·ios·objective-c
风启新尘1 天前
ios巨魔越狱
支持向量机·ios·智能手机
Digitally1 天前
没有充电器,如何给 iPhone 充电?
ios·iphone
bcbnb1 天前
基于Mach-O文件的动态库与静态库归属方案及API扫描实践
后端·ios
Aurora4191 天前
Compose的事件分发
客户端
2501_915921431 天前
VSCode 写 Swift 运行到 iPhone?快蝎 IDE 开发实战体验
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程