iOS 集合的內部存儲結構

前言

筆者最近看到兩道iOS筆試題目,當時就呆住了。ios

int a[5] = {1, 2, 3, 4, 5};
    int *ptr = (int *)(&a + 1);
    NSLog(@"a的地址 : %p", a);
    NSLog(@"a + 4 的地址: %p", a + 4);
    NSLog(@"ptr - 1 的地址 : %p", ptr - 1);
    NSLog(@"a + 1 的值 : %d", *(a + 1));
    NSLog(@"p - 1 的值 : %d", *(ptr - 1));
複製代碼

image.png

在C語言中,a和a[0]指向同一個地址。因此不難理解 a[1]的地址比a[0](即a)大了4。算法

聲明瞭a[5],存儲類型爲int。因此數組a的大小也肯定了,爲(5 * 4)。因此假設a地址爲0,ptr的地址是21。因爲p指針指向類型爲int,因此(p - 1)理所固然也指向a[4]。數組

對於動態數組,則須要藉助數據結構來實現。bash

因而筆者對iOS集合怎麼存儲提起了興趣。數據結構

image.png

測試一遍,發現結果爲23。感慨一句,NSSet到底是怎麼存儲的。測試

image.png

開始前,先提一句,集合中不能存儲基本數據類型,將保持與元素對象的強引用關係。spa

NSArray 和 NSMutableArray

NSArray : A static ordered collection of objects. NSMutableArray : A dynamic ordered collection of objects..net

和C不同,OC是門面向對象的語言。*array,固然指向數組對象的地址,而不是array[0]。換句話說,array和array[0]並不指向同一地方。那麼array[0]、array[1]、array[2]是怎麼找到該對象的,或者說怎麼存儲的呢?3d

因而筆者打下如下代碼,發現取不到array[0]返回的指針地址。也想不出來怎麼取。 指針

因而查閱到兩篇大牛寫的文章,CFArray 的歷史淵源及實現原理NSMutableArray原理揭露

在修改元素的操做中,CFArray 也略顯得暴力一些,先對數組進行大塊的分區操做,再按照順序填充數據,組合成爲一塊新的雙端隊列

簡單地說(筆者看得不怎麼懂,若是有誤,歡迎指出),數組的數據結構是雙端隊列,_size表示數組空間,_used表示多少個元素,_offset表示a[0]的偏移量。因此中間位置的操做會慢於兩端。

如圖,相似緩衝區嵌套 map 表。

當不夠容量時,擴容,修改_size,在緩衝區中標記下一塊內容頭地址在哪。有趣的是,_size只能增大,不會縮小。

NSSet 和 NSMutableSet

Set 和 Array的區別在於Set無序且沒有重複元素。


先來看Set是怎麼判斷重複元素的。

Set對元素是否重複的判斷在於兩個方法,- (NSUInteger)hash- (BOOL)isEqual:(id)objectiOS開發 之 不要告訴我你真的懂isEqual與hash!

在《Effective Objective-C 2.0》第8條:理解「對象等同性」提到:

根據等同性約定:若兩對象相等,則其哈希碼(hash)也相等,可是兩個哈希碼相同的對象卻未必相等。

若是沒有重寫這兩個方法,默認只比較指針值是否相等。

因此上面的筆試題中,Person沒有重寫這兩個方法。指針person2指向person1,因此被加到NSSet時,被當成同一個元素。而且person2.age修改成2,person1.age同理。因此最終輸出應該是23。


那麼Set存儲結構是怎麼樣的呢?

從上面咱們能夠看出,Set採用哈希表存儲,運用散列算法。因此元素在內存中是不連續的。

NSDictionary 和 NSMutableDictionary

NSDictionary :A static collection of objects associated with unique keys. NSMutableDictionary: A dynamic collection of objects associated with unique keys.

又是一篇筆者看不怎麼懂的文章NSDictionary 內部結構、實現原理

NSDictionary的結構是鏈地址哈希表。

相關文章
相關標籤/搜索