swift -- Array & Dictionary

2021-01-27  本文已影响0人  Mjs

Array

lazy

let numbers = Array(1...10)
let mapNumbers = numbers.lazy.map{$0 * 2}
print(mapNumbers)
·················
LazyMapSequence<Array<Int>, Int>(_base: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], _transform: (Function))

当我们调用的时候才会触发lazy

Array的创建

var numbers = [1,2,3,4,5,6]

var num : [Int] = Array()
var num1 : Array<Int> = Array()
//创建一个长度为10全为0的数组
var num2 = Array(repeating: 0, count: 10)

array存放的是数组的首地址,通过首地址去访问数据

(lldb) po withUnsafePointer(to: &numbers, {$0})
▿ 0x0000000100002128
  - pointerValue : 4294975784

(lldb) x/8g  0x0000000100002128
0x100002128: 0x00000001034223f0 0x0000000000000000
0x100002138: 0x0000000000000000 0x0000000000000000
0x100002148: 0x0000000000000000 0x0000000000000000
0x100002158: 0x0000000000000000 0x0000000000000000
(lldb) x/8g  0x00000001034223f0
0x1034223f0: 0x00007fff8f8a5260 0x0000000000000002
0x103422400: 0x0000000000000006 0x000000000000000c
0x103422410: 0x0000000000000001 0x0000000000000002
0x103422420: 0x0000000000000003 0x0000000000000004

array 在 append 时扩容是之前的2倍

数组扩容.png
(lldb) po withUnsafePointer(to: &numbers, {$0})
▿ 0x0000000100002150
  - pointerValue : 4294975824

(lldb) x/8g  0x0000000100002150
0x100002150: 0x0000000103988020 0x0000000000000000
0x100002160: 0x0000000000000000 0x0000000000000000
0x100002170: 0x0000000000000000 0x0000000000000000
0x100002180: 0x0000000000000000 0x0000000000000000
//numbers.append(7)之后
(lldb) x/8g  0x0000000100002150
0x100002150: 0x0000000103875a10 0x0000000000000000
0x100002160: 0x0000000000000000 0x0000000000000000
0x100002170: 0x0000000000000000 0x0000000000000000
0x100002180: 0x0000000000000000 0x0000000000000000
(lldb) x/8g  0x0000000103875a10
0x103875a10: 0x00007fff8f8a5260 0x0000000000000002
0x103875a20: 0x0000000000000007 0x0000000000000018
0x103875a30: 0x0000000000000001 0x0000000000000002
0x103875a40: 0x0000000000000003 0x0000000000000004

在数组添加一个7之后,地址发生了改变
这种在 Swift 中我们就叫做写时复制

Dictionary

var dic = ["Kody": "Swift", "Hank": "逆向", "Cat": "强化班", "Cooci" : "⼤师班"]
dic1.png

所以这⾥我们需要搞明⽩⼀件事情: _NativeDictionary 是什么东⻄?


dic2.png dic3.png dic4.png dic5.png dic6.png

这个时候我们再倒回去看⼀下 Dictionary 的初始化


dic7.png dic8.png dic9.png
可以看到 Dictionary 内部只有⼀个成员变量 _variant , 类型是 _Varient 。_Varient 是⼀个关联 值的枚举类型。 这个时候我们能够得出来当前 Dictionary 内部成员变量间的关系 dic10.png dic11.png
(lldb) po withUnsafePointer(to: &dic, {$0})
▿ 0x0000000100002140
  - pointerValue : 4294975808
//这里是值类型,直接储存的地址
(lldb) x/8g 0x0000000100002140
0x100002140: 0x0000000100622a60 0x0000000000000000
0x100002150: 0x0000000000000000 0x0000000000000000
0x100002160: 0x0000000000000000 0x0000000000000000
0x100002170: 0x0000000000000000 0x0000000000000000
//得出来的结构
(lldb) x/8g 0x0000000100622a60
0x100622a60: 0x00007fff8f8a5590 0x0000000000000002
0x100622a70: 0x0000000000000004 0x0000000000000006
0x100622a80: 0x60e4d22100000003 0x0000000100622a60
0x100622a90: 0x0000000100622aa8 0x0000000100622b28
//得出来的key/value
(lldb) x/8g 0x0000000100622b28
0x100622b28: 0x8fe788b8e5a4bce2 0xa9000000000000ad
0x100622b38: 0x0000000000000000 0x0000000000000000
0x100622b48: 0x0000007466697753 0xe500000000000000
0x100622b58: 0x00009190e58680e9 0xa600000000000000
Dictionary插⼊⼀个值
setValue.png
lookup.png

_find 函数⽤于找到Key对应的bucket 需要指定需要指定从哪个bucket开始寻找,因此需要 _buckey(key) 函数的配合 如果参数key和某个bucket中的Key匹配,则返回这个bucket的位置 如果没有找到,则返回接下来的第⼀个洞,表示key可以插⼊到这⾥ 通过位图判断当前bucket是不是⼀个洞 这种算法被称为线性探测


find.png
我们的 key 是遵循了 hashable 协议的。这⾥我们先来看⼀下 hashable 协议

当⼀个类型遵循了 hashable 的协议之后,会有⼀个哈希值,我们利⽤这个哈希值来判断两个类型是不 是同⼀个


hashValue.png
hashTable.png
isValid.png
校验.png
如果当前返回的结果是true,那么就以为着当前的插槽有值,反之没值。

所以我们是以key.hashValue &mask 计算出index 看是否有值,通过开放寻址法找到位置。如果存在我们就覆盖不存在就插入。

上一篇下一篇

猜你喜欢

热点阅读