这里每天分享一个 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、子元素类型略有不同
Array
和 Set
的子元素类型都是范型,但是 Set 要求子元素必须实现 Hashable 协议(可哈希),而 Array
对子元素没有要求。
标准库中的大多数类型(字符串、数字、Bool)都是可哈希的。
但如果是自定义的类型,就需要先遵守 Hashable
协议才能存进 Set
中,Set
底层也是根据 Hashable
中的 hashValue
值来去重的。
性能方面比较
Array
和 Set
在 Swift 中都是通过泛型和协议来实现的。
在底层,Array
使用连续内存存储元素,这也保证了它的元素顺序是固定的。连续的内存空间也使得访问元素时速度快,但插入和删除元素可能需要移动其他元素,导致性能下降。
而 Set
则使用哈希表进行存储(跟字典原理相同),存储的内存是不连续的,哈希表好处是查找、添加、删除操作速度都很快(平均时间复杂度为O(1)),但坏处是会消耗更多内存。
这里每天分享一个 iOS 的新知识,快来关注我吧
本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!