iOS 数组containsObject:方法
今年上半年打算巩固一下基础知识,将工作和学习中遇到的疑惑尽量搞清楚原理。作为一个菜鸟级别的程序员,我深深的体会到算法和基础的重要性,如果说算法是内功,那么基础就是下盘,只有下盘稳住了,上面才不会轻易倒。当然,我这里刻意避开算法不谈,实际上我知道自己不是研究算法的料,想来懂一些基本的算法就好了,以后若是遇到莫大的机缘,习得一两本内功心法,那时我可能要上天了。哈哈,不晓得能不能听懂我的胡言乱语。
之前遇到过一个问题,从数据库中读数据后发现有重复的数据出现,而且读数据库是采取一次性读完的方式,从理论上讲是不会出现重复数据的现象的。查了一下代码,发现并没有什么问题,因为时间的原因,而且是帮别人解决问题,所以也就没有深究。最后写了个去重复的方法,用来保证不会显示同样的数据。去重复的方法很简单,但是重点不是它,我想说的是如果想偷懒的童鞋想用数组中的containsObject:方法去重复就要注意了,因为这个方法没有我们想象的那么强大。我用两种方式来检测这个方法到底在做什么事。
1.使用字符串测试。首先创建几个字符串,@"123", @"456", @"123", @"222",把它们添加到数组中去。为了节省时间,直接放入不可变数组中,NSArray *strArray = @[@"123", @"456", @"123", @"222"];然后创建一个可变数组,NSMutableArray *testStrArray = [NSMutableArray array];依次将strArray中的对象添加到testStrArray中,在此之前用containsObject:判定testStrArray中是否已经存在了,如果没有存在,则添加。看如下代码:
//1.字符串常量的比较,测试对象:@"123", @"456", @"123", @"222"
NSString *str1 = @"";
NSString *str2 = @"";
NSString *str3 = @"";
NSArray *strArray = @[str1, str2, str3];
NSMutableArray *testStrArray = [NSMutableArray array];
for (NSString *str in strArray)
{
if ([testStrArray containsObject:str])
{
NSLog(@"%@ 已存在 地址是 %p", str, &str);
}
else
{
NSLog(@"%@ %p", str, &str);
[testStrArray addObject:str];
}
}
NSLog(@"%@ %p", testStrArray, &testStrArray);
NSLog(@"%p", str1);
NSLog(@"%p", str2);
NSLog(@"%p", str3);
下面看看输出结果:

看看最下面三行,你会发现第一个和第三的地址相同,然后在数组中添加了两个对象,说明这个方法能够将字符串去重复。那么到底是根据什么去重复的我们不得而知,因为这里有两个因素:1.字符串内容相同,都是@"123";2.地址相同。下面用自定义的对象测试完了之后,再来说说为什么str1和str3的地址相同,以及在for循环中打印出来的str的地址为什么相同。
2.使用自定义的对象测试,套路跟字符串一样,代码如下:
TestObject *testObj1 = [[TestObject alloc] initWithName:@""];
TestObject *testObj2 = [[TestObject alloc] initWithName:@""];
TestObject *testObj3 = [[TestObject alloc] initWithName:@""];
TestObject *testObj4 = [[TestObject alloc] initWithName:@""];
NSArray *testArray = @[testObj1, testObj2, testObj3, testObj4, testObj1];
NSMutableArray *testMutableArray = [NSMutableArray array];
for (int i=;i<[testArray count];i++)
{
TestObject *testObj = testArray[i];
if ([testMutableArray containsObject:testObj])
{
NSLog(@"%@-------------%p", testObj, &testObj);
}
else
{
// NSLog(@"%@ %p %li", testObj, &testObj, sizeof(testObj));
[testMutableArray addObject:testObj];
}
}
NSLog(@"%@", testMutableArray);
NSLog(@"1 %p", testObj1);
NSLog(@"2 %p", testObj2);
NSLog(@"3 %p", testObj3);
NSLog(@"4 %p", testObj4);
输出的结果如下:

第一个对象添加了两次,去重复将其去掉了,然而内容相同的testObj1和testObj3并没有去重复,由此可以看出,这个方法并不能将内容相同的对象区别开来。
其实,做这个实验是想说明,containsObject:是在比较内存地址,即使两个对象内容完全一样,地址不同,那也是不同的。我个人认为这个方法应该叫是否存在同一个对象,因为根据字面意思,我们有时候可能会因为想偷懒,而人为的把它假想成内容一样就是对象一样。
接下来说说字符串这个东西,不可变字符串是一种很特殊的对象,它初始化的时候,通常指向字符串常量,所以str = @"123"表示的是,str存放了@"123"地址,固第一种测试中的str1和str3地址相同。在for循环中打印str的地址时,发现都相同,是因为,str保存的是数组的首地址,所以都一样。
有关内存地址的知识,说实话我也不是很清楚,但是我会在后面的文章中,慢慢的进行整理,希望能将这一块彻底解决。
iOS 数组containsObject:方法的更多相关文章
- IOS开发_中遍历数组的方法及比较
数组,做为一种常用的数据类型,频繁出现在编码中,其中肯定少不了对数组的遍历,本博文对数组遍历,进行一下自己的归纳,如果是大牛,一笑而过就好,互相学习,欢迎指正. 话不多说直接进入主题 首先创建一个数组 ...
- iOS常用公共方法
iOS常用公共方法 字数2917 阅读3070 评论45 喜欢236 1. 获取磁盘总空间大小 //磁盘总空间 + (CGFloat)diskOfAllSizeMBytes{ CGFloat si ...
- iOS数组使用
相关链接: ios数组基本用法和排序 NSArray 排序汇总 iOS 数组排序方法 IOS-筛选数组内的元素 关于EnumerateObjectsUsingBlock和for-in之间的较量 [iO ...
- [BS-02] iOS数组、字典、NSNumber 新写法—— @[]、@{}
IOS数组.字典.NSNumber 新写法—— @[].@{} //标准写法 NSNumber * number = [NSNumber numberWithInt:]; NSArray * ar ...
- iOS 常用公共方法
iOS常用公共方法 1. 获取磁盘总空间大小 //磁盘总空间 + (CGFloat)diskOfAllSizeMBytes{ CGFloat size = 0.0; NSError *error; N ...
- ES6之数组扩展方法【一】(相当好用)
form 转化为真正的数组 先说一下使用场景,在Js中,我们要经常操作DOM,比如获取全部页面的input标签,并且找到类型为button的元素,然后给这个按钮注册一个点击事件,我们可能会这样操作: ...
- 再探JS数组原生方法—没想到你是这样的数组
最近作死又去做了一遍javascript-puzzlers上的44道变态题,这些题号称"JS语言专业八级"的水准,建议可以去试试,这里我不去解析这44道题了, ...
- 一些ES5的操作数组的方法
在ES5规范中新增了不少操作数组的方法,特此罗列一下以备使用 1. forEach循环 有点类似jQuery的each循环 [12,23,36,4,5].forEach(function(v,k){ ...
- 关于ES3、ES5、ES6以及ES7所有数组的方法(api)的总结
起因:工作用经常用到操作数组的方法,这里进行一下总结,我尽量以简洁的语言概括每个方法(api)的作用.如果您想快速定位,可以Control+F 然后搜相应的方法即可定位 :) ES3的数组方法 joi ...
随机推荐
- NGUI的一个bug记录
在当前帧内触发按钮事件,然后把click事件的list删去,再添加,这时候会再次触发. 不确定,先记一下
- Unity 扩展编辑器
扩展Inspector界面 继承自Editor,添加CustomEditorAttribute,传入定制的类型 定制显示的类型要求: 类型中所有的public 字段都会自动暴露给Inspector编辑 ...
- rdb 和 aof
Redis 中 默认会开启rdb 持久化方式,aof 默认不开启,Redis 提供不同级别的持久化方式rdb: 在指定的时间间隔对你的数据进行快照存储aof:记录每次Redis服务写操作,当Redis ...
- tomcat web 修改logo
第一种: 打开tomcat目录,进入 D:\tomcat\apache-tomcat-7.0.50-1\webapps\ROOT 找到favicon.ico图标 然后替换成自己的 第二种: 由于tom ...
- html 基本标签 ---字体
<b> </b>加粗 <i> </i> 斜体 <del> </del> 删除 <ins> </ins> ...
- MapReduce编程实例4
MapReduce编程实例: MapReduce编程实例(一),详细介绍在集成环境中运行第一个MapReduce程序 WordCount及代码分析 MapReduce编程实例(二),计算学生平均成绩 ...
- spring 集成 redis -- pub/sub
redis除了常用的当做缓存外,还可以当做简单的消息中间件,实现消息发布订阅 spring集成redis,可以使用spring-data-redis 首先引入相关maven依赖(此处我spring相关 ...
- impala+kudu
[impala建表]kudu的表必须有主键,作为分区的字段需排在其他字段前面. [range分区](不推荐)CREATE TABLE KUDU_WATER_HISTORY ( id STRING, y ...
- python post get请求
安装 Requests pip install requests import requests requests.get('https://github.com/timeline.json') 使用 ...
- 请写出一段表单提交的HTML代码,表单名称为form1,提交方式为post,提交地址为submit.asp
请写出一段表单提交的HTML代码,表单名称为form1,提交方式为post,提交地址为submit.asp 解答: <form name=”form1” method=”post” action ...