首页 > 代码库 > iOS 数组containsObject:方法
iOS 数组containsObject:方法
今年上半年打算巩固一下基础知识,将工作和学习中遇到的疑惑尽量搞清楚原理。作为一个菜鸟级别的程序员,我深深的体会到算法和基础的重要性,如果说算法是内功,那么基础就是下盘,只有下盘稳住了,上面才不会轻易倒。当然,我这里刻意避开算法不谈,实际上我知道自己不是研究算法的料,想来懂一些基本的算法就好了,以后若是遇到莫大的机缘,习得一两本内功心法,那时我可能要上天了。哈哈,不晓得能不能听懂我的胡言乱语。
之前遇到过一个问题,从数据库中读数据后发现有重复的数据出现,而且读数据库是采取一次性读完的方式,从理论上讲是不会出现重复数据的现象的。查了一下代码,发现并没有什么问题,因为时间的原因,而且是帮别人解决问题,所以也就没有深究。最后写了个去重复的方法,用来保证不会显示同样的数据。去重复的方法很简单,但是重点不是它,我想说的是如果想偷懒的童鞋想用数组中的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保存的是数组的首地址,所以都一样。
有关内存地址的知识,说实话我也不是很清楚,但是我会在后面的文章中,慢慢的进行整理,希望能将这一块彻底解决。
iOS 数组containsObject:方法