不積跬步無以至千里。 ——送給第一篇博客
問題
NSMutableDictionary是怎么實現的?
解決方案
學習實現原理最好的辦法就是查看源代碼,這部分代碼也很容易找到
/**************** Mutable Dictionary ****************/
@interface NSMutableDictionary<KeyType, ObjectType> : NSDictionary<KeyType, ObjectType>
- (void)removeObjectForKey:(KeyType)aKey;
- (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCapacity:(NSUInteger)numItems NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
@end
@interface NSMutableDictionary<KeyType, ObjectType> (NSExtendedMutableDictionary)
- (void)addEntriesFromDictionary:(NSDictionary<KeyType, ObjectType> *)otherDictionary;
- (void)removeAllObjects;
- (void)removeObjectsForKeys:(NSArray<KeyType> *)keyArray;
- (void)setDictionary:(NSDictionary<KeyType, ObjectType> *)otherDictionary;
- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key NS_AVAILABLE(10_8, 6_0);
@end
從源代碼中我們可以看到NSMutableDictionary是繼承自NSDictionary的,但是添加了增加刪除等方法常潮。將NSDictionary變成可變的字典類型。我們再打開NSDictionary的實現代碼看一下楷力。
@interface NSDictionary<KeyType, ObjectType> (NSExtendedDictionary)
@property (readonly, copy) NSArray<KeyType> *allKeys;//key數組
- (NSArray<KeyType> *)allKeysForObject:(ObjectType)anObject;
@property (readonly, copy) NSArray<ObjectType> *allValues;//value數組
@property (readonly, copy) NSString *description;
我們可以看到NSDictionary中包含了兩個NSArray,及一個對應Key的NSArray和一個對應Value的NSArray孵户。
從以上兩端代碼中我們可以看到NSDictionary以及NSArray的屬性均為(readonly,copy)類型的萧朝,顧名思義其值是只讀的,不可改變夏哭。這也符合了介紹检柬,但是NSMutableDictionary以及NSMutableArray均繼承于屬性不可變的父類,那他是怎么實現可變的呢?由于SDK只開放了.h文件(其實就是只告訴了我們API)何址,沒有開放.m文件里逆,我們無法獲得其實現細節(jié)。我的猜測是把內容拷貝出來重新賦值給新的對象用爪,在替換原地址原押,但是感覺好蠢。以后有能力可以細究一下偎血。
意外發(fā)現
看源代碼的時候發(fā)現NSArray中集成二分查找诸衔,但二分查找一般針對排序數組會有比較快的效率。百度了一下颇玷,發(fā)現一篇文章 ,這篇文章對iOS的各種集合類做了一定的分析笨农。其中也提到了一開始對apple這種將很多集合分為可變和不可變的感覺很怪異,不過這樣做可以使得其線程安全帖渠,這樣其付出的代價也是值得的谒亦,有興趣可以拜讀一下。
typedef NS_OPTIONS(NSUInteger, NSBinarySearchingOptions) {
NSBinarySearchingFirstEqual = (1UL << 8),
NSBinarySearchingLastEqual = (1UL << 9),
NSBinarySearchingInsertionIndex = (1UL << 10),
};
- (NSUInteger)indexOfObject:(ObjectType)obj inSortedRange:(NSRange)r options:(NSBinarySearchingOptions)opts usingComparator:(NSComparator)cmp NS_AVAILABLE(10_6, 4_0); // binary search