首页 > 代码库 > 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:方法