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

相关推荐
2501_9160074719 小时前
iOS 压力测试的工程化体系,构建高强度、多维度、跨工具协同的真实负载测试流程
android·ios·小程序·uni-app·cocoa·压力测试·iphone
2501_9160088921 小时前
API接口调试全攻略 Fiddler抓包工具、HTTPS配置与代理设置实战指南
前端·ios·小程序·https·fiddler·uni-app·webview
2501_915921431 天前
iOS 开发者工具推荐,构建从调试到性能优化的多维度生产力工具链(2025 深度工程向)
android·ios·性能优化·小程序·uni-app·iphone·webview
00后程序员张1 天前
全面解析网络抓包工具使用:Wireshark和TCPDUMP教程
网络·ios·小程序·uni-app·wireshark·iphone·tcpdump
游戏开发爱好者81 天前
Mac 抓包软件怎么选?从 HTTPS 调试、TCP 数据流分析到多工具协同的完整抓包方案
tcp/ip·macos·ios·小程序·https·uni-app·iphone
马拉萨的春天1 天前
iOS中广告SDK如何判断一个广告是否真实展示
macos·ios·cocoa
ajassi20001 天前
开源 Objective-C IOS 应用开发(十九)视频的播放
ios·开源·objective-c
2501_915918411 天前
苹果上架 iOS 应用的工程实践,一次从零到上线的完整记录
android·ios·小程序·https·uni-app·iphone·webview
ajassi20001 天前
开源 Objective-C IOS 应用开发(二十二)自定义控件--车速仪表盘
ios·开源·objective-c
從南走到北1 天前
JAVA国际版同城跑腿源码快递代取帮买帮送同城服务源码支持Android+IOS+H5
android·java·ios·微信小程序