今年上半年打算鞏固一下基礎知識,將工作和學習中遇到的疑惑盡量搞清楚原理。作為一個菜鳥級別的程序員,我深深的體會到算法和基礎的重要性,如果說算法是內功,那么基礎就是下盤,只有下盤穩住了,上面才不會輕易倒。當然,我這里刻意避開算法不談,實際上我知道自己不是研究算法的料,想來懂一些基本的算法就好了,以后若是遇到莫大的機緣,習得一兩本內功心法,那時我可能要上天了。哈哈,不曉得能不能聽懂我的胡言亂語。
之前遇到過一個問題,從數據庫中讀數據后發現有重復的數據出現,而且讀數據庫是采取一次性讀完的方式,從理論上講是不會出現重復數據的現象的。查了一下代碼,發現並沒有什么問題,因為時間的原因,而且是幫別人解決問題,所以也就沒有深究。最后寫了個去重復的方法,用來保證不會顯示同樣的數據。去重復的方法很簡單,但是重點不是它,我想說的是如果想偷懶的童鞋想用數組中的containsObject:方法去重復就要注意了,因為這個方法沒有我們想象的那么強大。我用兩種方式來檢測這個方法到底在做什么事。
1.使用字符串測試。首先創建幾個字符串,@"123", @"456", @"123", @"222",把它們添加到數組中去。為了節省時間,直接放入不可變數組中,NSArray *strArray = @[@"123", @"456", @"123", @"222"];然后創建一個可變數組,NSMutableArray *testStrArray = [NSMutableArray array];依次將strArray中的對象添加到testStrArray中,在此之前用containsObject:判定testStrArray中是否已經存在了,如果沒有存在,則添加。看如下代碼:
1 //1.字符串常量的比較,測試對象:@"123", @"456", @"123", @"222" 2 NSString *str1 = @"123"; 3 NSString *str2 = @"345"; 4 NSString *str3 = @"123"; 5 NSArray *strArray = @[str1, str2, str3]; 6 NSMutableArray *testStrArray = [NSMutableArray array]; 7 for (NSString *str in strArray) 8 { 9 if ([testStrArray containsObject:str]) 10 { 11 NSLog(@"%@ 已存在 地址是 %p", str, &str); 12 } 13 else 14 { 15 NSLog(@"%@ %p", str, &str); 16 [testStrArray addObject:str]; 17 } 18 } 19 NSLog(@"%@ %p", testStrArray, &testStrArray); 20 NSLog(@"%p", str1); 21 NSLog(@"%p", str2); 22 NSLog(@"%p", str3);
下面看看輸出結果:

看看最下面三行,你會發現第一個和第三的地址相同,然后在數組中添加了兩個對象,說明這個方法能夠將字符串去重復。那么到底是根據什么去重復的我們不得而知,因為這里有兩個因素:1.字符串內容相同,都是@"123";2.地址相同。下面用自定義的對象測試完了之后,再來說說為什么str1和str3的地址相同,以及在for循環中打印出來的str的地址為什么相同。
2.使用自定義的對象測試,套路跟字符串一樣,代碼如下:
1 TestObject *testObj1 = [[TestObject alloc] initWithName:@"123"]; 2 TestObject *testObj2 = [[TestObject alloc] initWithName:@"1234"]; 3 TestObject *testObj3 = [[TestObject alloc] initWithName:@"123"]; 4 TestObject *testObj4 = [[TestObject alloc] initWithName:@"1235"]; 5 NSArray *testArray = @[testObj1, testObj2, testObj3, testObj4, testObj1]; 6 NSMutableArray *testMutableArray = [NSMutableArray array]; 7 for (int i=0;i<[testArray count];i++) 8 { 9 TestObject *testObj = testArray[i]; 10 if ([testMutableArray containsObject:testObj]) 11 { 12 NSLog(@"%@-------------%p", testObj, &testObj); 13 } 14 else 15 { 16 // NSLog(@"%@ %p %li", testObj, &testObj, sizeof(testObj)); 17 [testMutableArray addObject:testObj]; 18 } 19 } 20 NSLog(@"%@", testMutableArray); 21 NSLog(@"1 %p", testObj1); 22 NSLog(@"2 %p", testObj2); 23 NSLog(@"3 %p", testObj3); 24 NSLog(@"4 %p", testObj4);
輸出的結果如下:

第一個對象添加了兩次,去重復將其去掉了,然而內容相同的testObj1和testObj3並沒有去重復,由此可以看出,這個方法並不能將內容相同的對象區別開來。
其實,做這個實驗是想說明,containsObject:是在比較內存地址,即使兩個對象內容完全一樣,地址不同,那也是不同的。我個人認為這個方法應該叫是否存在同一個對象,因為根據字面意思,我們有時候可能會因為想偷懶,而人為的把它假想成內容一樣就是對象一樣。
接下來說說字符串這個東西,不可變字符串是一種很特殊的對象,它初始化的時候,通常指向字符串常量,所以str = @"123"表示的是,str存放了@"123"地址,固第一種測試中的str1和str3地址相同。在for循環中打印str的地址時,發現都相同,是因為,str保存的是數組的首地址,所以都一樣。
有關內存地址的知識,說實話我也不是很清楚,但是我會在后面的文章中,慢慢的進行整理,希望能將這一塊徹底解決。
