關鍵詞:哈希表、weak、RunLoop、哈希衝突
數組
哈希表(hash table,也叫散列表),是根據鍵(key)直接訪問訪問在內存儲存位置的數據結構。bash
哈希表的關鍵思想是使用哈希函數將鍵映射到存儲桶。更確切地說,
- 當咱們插入一個新的鍵時,哈希函數將決定該鍵應該分配到哪一個桶中,並將該鍵存儲在相應的桶中;
- 當咱們想要搜索一個鍵時,哈希表將使用相同的哈希函數來查找對應的桶,並只在特定的桶中進行搜索。
Hash在iOS中的應用
weak表
weak表採用的是一個全局的HashMap嵌套數組的結構存儲數據的,銷燬對象(weak指針指向的對象)的時候,根據對象從HashMap中找到存放全部指向該對象的weak指針的數組,而後將數組中的全部元素都置爲nil。
weak的最大特色就是在對象銷燬的時候,自動置nil,減小訪問野指針的風險,這也是設計weak的初衷。方案設計實現好後,weak指針置nil的基本步驟:
- 對象dealloc的時候,從全局的HashMap中,根據一個惟一表明對象的值做爲key,找到存儲全部指向該對象的weak指針的數組
- 將數組中的全部元素都置爲nil
weak表結構及細節能夠參考下圖及連接數據結構
struct SideTable {
// 保證原子操做的自旋鎖
spinlock_t slock;
// 引用計數的 hash 表
RefcountMap refcnts;
// weak 引用全局 hash 表
weak_table_t weak_table;
}複製代碼

推薦閱讀 https://www.desgard.com/weak/ide
Runloop
線程和 RunLoop 之間是一一(子線程能夠沒有)對應的,其關係是保存在一個全局的 Dictionary 裏。線程剛建立時並無 RunLoop,若是你不主動獲取,那它一直都不會有。RunLoop 的建立是發生在第一次獲取時,RunLoop 的銷燬是發生在線程結束時。你只能在一個線程的內部獲取其 RunLoop(主線程除外)。
推薦閱讀 blog.ibireme.com/2015/05/18/…函數
其餘
還有不少其餘的點也用到了哈希表,能夠參考下圖

Hash的優點
- 優勢 :哈希表能夠提供快速的操做。
- 缺點 :哈希表一般是基於數組的,數組建立後難於擴展。 也沒有一種簡便的方法能夠以任何一種順序〔例如從小到大)遍歷表中的數據項。
綜上,若是不須要有序遍歷數據,井且能夠提早預測數據量的大小。那麼哈希表在速度和易用性方面是無與倫比的。
Hash常見問題及解法
哈希衝突
當關鍵字值域遠大於哈希表的長度,並且事先並不知道關鍵字的具體取值時。衝突就不免會發 生。另外,當關鍵字的實際取值大於哈希表的長度時,並且表中已裝滿了記錄,若是插入一個新記錄,不只發生衝突,並且還會發生溢出
- 用開放定址法解決衝突的作法是:當衝突發生時,使用某種探查(亦稱探測)技術在散列表中造成一個探查(測)序列。沿此序列逐個單元地查找,直到找到給定 的關鍵字,或者碰到一個開放的地址(即該地址單元爲空)爲止(若要插入,在探查到開放的地址,則可將待插入的新結點存人該地址單元)。查找時探查到開放的 地址則代表表中無待查的關鍵字,即查找失敗。
- 拉鍊法解決衝突的作法是:將全部關鍵字爲同義詞的結點連接在同一個單鏈表中。若選定的散列表長度爲m,則可將散列表定義爲一個由m個頭指針組成的指針數 組T[0..m-1]。凡是散列地址爲i的結點,均插入到以T[i]爲頭指針的單鏈表中。T中各份量的初值均應爲空指針。在拉鍊法中,裝填因子α能夠大於 1,但通常均取α≤1。
存在重複元素(leetcode題目)
基本就是使用哈希表來查重
兩數之和(leetcode題目)
使用哈希表在數組中找出