认识数组
1)数组是一个有序的元素序列,支持随机存储。索引从0开始,索引访问越界会抛出运行时异常。注意与C语言数组不同。
----------------NSArray初始化------------
//工厂方法 最后放nil 表示结束 它不是元素
NSArray *array1=[NSArray arrayWithObjects:@"Shanghai",@"Beijing",@"New York",@"Paris", nil];
//内存分配alloc+init初始化
NSArray *array2=[[NSArray alloc] initWithObjects:@"Shanghai",@"Beijing",@"New York",@"Paris", nil];
//使用字面常量 不需要Nil
NSArray *array3=@[@"Shanghai",@"Beijing",@"New York",@"Paris"];
NSLog(@"array1 count: %lu" ,array1.count);//4
NSLog(@"array2 count: %lu" ,array2.count);//4
NSLog(@"array3 count: %lu" ,array3.count);//4
NSLog(@"array1: %@" ,array1);//按字符串方式打印出来
2)NSArray被定义为class,引用类型,拷贝时具有引用语义。
3)NSArray的元素必须是对象,即NSObject的子类:
*如为基本数据类型,需要用NSNumber封装为对象类型后,才能放入数组里面。
*如果为C语言结构类型,需要用NSValue封装为对象类型后,才能放入数组中。
*数组元素可以是不同对象类型,可能会有类型不安全。(取值的时候不清楚是什么类型)
//----------------数组元素-------------
NSString *text=@"Panda";//字符串对象
NSInteger number=100;//不是对象 是从新定义后的整数 基于cpu架构 还是值类型
NSNumber *numberObject1=
[NSNumber numberWithInteger:number ];//使用NSNumber将NSInteger包装为对象
NSNumber *numberObject2=@300u;//使用字面常量初始化
Point point;//结构类型也不行 需要使用NSValue将struct包装为对象 编码方式将Point写进去
point.h=100;
point.v=200;
NSValue *pointObject=
[NSValue value:&point withObjCType:@encode(Point)];//使用NSValue将struct包装为对象
NSNull* nullValue=[NSNull null];
NSArray *array4=@[text, numberObject1,numberObject2,pointObject, nullValue];
NSLog(@"array4: %@" ,array4);
4)NSArray具有常量性:长度和元素指针都不能更改。但指针指向的对象内部可以更改。
//----------------数组的常量性-------------
BLNPoint *p1=[[BLNPoint alloc] initWithX:10 WithY:20];
BLNPoint *p2=[[BLNPoint alloc] initWithX:20 WithY:40];
BLNPoint *p3=[[BLNPoint alloc] initWithX:30 WithY:60];
BLNPoint *p4=[[BLNPoint alloc] initWithX:40 WithY:80];
NSArray *array5=@[p1,p2,p3,p4];
NSLog(@"array5: %@", array5);
BLNPoint *p5=[[BLNPoint alloc] initWithX:50 WithY:100];
//1. 更改元素长度-----不可以!
//[array5 addObject:p5];
//2. 更改元素指针-----不可以!
//array5[0]=p5;
//3. 更改指针指向的内容-----可以!
for(int i=0;i<array5.count;i++){
BLNPoint *pt= array5[i];//取出每个元素
pt.x++;//将指针里面指向的内容更改
pt.y++;
}
NSLog(@"array5: %@", array5);
数组的常用操作:
//----------------数组的遍历-------------
最快-Fast Enumeration,直接访问内存,优化索引检查,快5-10倍 建议用这种
//快速枚举 如果不知道类型 用id 或者 object
for ( BLNPoint* point in array5)
{
point.x++;
point.y++;
}
较慢-NSEnumerator遍历 索引检查+动态消息调用
//迭代器模式
NSEnumerator *enumerator = [array5 objectEnumerator];
BLNPoint* item;
while (item = [enumerator nextObject])//消息分发
{
item.x++;
item.y++;
}
最慢-For循环访问:索引检查+动态消息调用
//for循环
for (int i=0; i<array5.count; i++) {
NSLog(@"array5[%d],%@",i,array5[i]);//访问索引
}
数组查找
1)indexofobject查找是否存在“值相等”的对象(类型需要实现isEqual)
2)indexofobjectIdenticalTo 查找是否存在“指针相等”的对象
//数组查找
BLNPoint* target=[[BLNPoint alloc] initWithX:33 WithY:63];
NSUInteger index1=[array5 indexOfObject:target];//查找值是否相等
NSUInteger index2=[array5 indexOfObjectIdenticalTo:p3];//指针引用是否相等
NSLog(@"find at %lu", index1);//find at 2
NSLog(@"find at %lu", index2);//find at 2
在进行查找值是否相等的时候 需要写这个方法:
- (BOOL)isEqual:(id)anObject{
if (! [anObject isKindOfClass: [BLNPoint class]] ){
return false;
}
BLNPoint* other=anObject;
return (self.x==other.x && self.y==other.y);
}
数组排序
不改变原数组(常量性),返回新数组
//数组排序 字母排序 不更改里面的内容 取返回值给新的数组
NSArray* sortArray1=[array1 sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"array1: %@" ,array1);
NSLog(@"sortArray1: %@" ,sortArray1);
结果:
array1: (
Shanghai,
Beijing,
"New York",
Paris
)
sortArray1: (
Beijing,
"New York",
Paris,
Shanghai
)
使用NSMutableArray
NSMutableArray支持更改数组长度和元素指针。为NSArray的子类。
//初始化
NSMutableArray *muArray1=[NSMutableArray arrayWithObjects:p1,p2,p3,p4, nil];
NSLog(@"before change, muArray1: %@",muArray1);
BLNPoint *p6=[[BLNPoint alloc] initWithX:60 WithY:120];
BLNPoint *p7=[[BLNPoint alloc] initWithX:70 WithY:140];
//修改元素
[muArray1 addObject:p5];//增加一个元素
[muArray1 removeObjectAtIndex:2];//将p3元素删除
[muArray1 insertObject:p6 atIndex:1];//在1位置上插入p6
muArray1[0]=p7; //[muArray1 setObject:p7 atIndexedSubscript:0];
NSLog(@"after change, muArray1: %@",muArray1);
NSMutableArray初始化后,会分配一个缓存容量capacity,一般大于实际元素数量,当长度增长时,如实际需求大于capacity会以近似2倍的方法指数增长。伴随代价:
分配新的堆内存2capacity
*将原来堆内存上的元素拷贝到新的内存
*释放原来的堆内存
//预估容量
int count=100;
NSMutableArray *muArray2=[NSMutableArray arrayWithCapacity:10];
for (int i=0; i< count; i++) {
BLNPoint *pt=[[BLNPoint alloc] initWithX:i*10 WithY:i*20];
[muArray2 addObject: pt];
}
最佳实践:估计好capacity,预先分配一定容量,避免以后增长。
尽量避免使用insertObject:atIndex:和removeObjectAtIndex操作,因为会改变数组元素序列,涉及大量内存拷贝操作,代价高。前移后移的操作。
认识NSSet集合(无序)
NSSet是一个无序的集合,其存储的对象不能重复。
NSSet被定义为class,引用类型,拷贝时具有引用语义。
常量集合NSSet,可变集合:NSMutableSet:
常量性:长度和指针元素都不能更改。但指针指向的对象内部可以更改。
创建NSMutableSet时用initwithcapacity提前设置capacity
支持Fast Enumeration和NSEnumerator变量,前者较快。
void setDemo()
{
//---------------- NSSet 与 NSMutableSet-------------
//初始化
NSSet *set1 =
[NSSet setWithObjects:@"Shanghai",@"Beijing",@"New York",@"Paris", nil];
NSLog(@"set1 count: %lu", set1.count);
NSMutableSet *set2 =
[NSMutableSet setWithObjects:@"Shanghai",@"Beijing",@"New York",@"Paris", nil];
[set2 addObject:@"London"];
[set2 addObject:@"Paris"];
[set2 removeObject:@"Beijing"];
NSLog(@"set2 count: %lu", set2.count);
//判断是否包含某个对象
if([set2 containsObject:@"Shanghai"])
{
NSLog(@"set2 contains Shanghai");
}
//遍历
for(NSString* item in set2)
{
NSLog(@"%@", item);
}
}
认识字典NSDictionary
NSDictionary是一个存储key-value的无序集合,key唯一,value可重复。
NSDictionary被定义为class,引用类型,拷贝时具有引用语义。
常量集合NSDictionary,可变集合:NSMutableDictionary:
常量性:长度和指针元素都不能更改。但指针指向的对象内部可以更改。
创建NSMutableDictionary时用initwithcapacity提前设置capacity
支持Fast Enumeration和NSEnumerator变量,前者较快。
void dictionaryDemo()
{
//---------------- NSDictionary 与 NSMutableDictionary-------------
BLNPoint *p1=[[BLNPoint alloc] initWithX:10 WithY:20];
BLNPoint *p2=[[BLNPoint alloc] initWithX:20 WithY:40];
BLNPoint *p3=[[BLNPoint alloc] initWithX:30 WithY:60];
BLNPoint *p4=[[BLNPoint alloc] initWithX:40 WithY:80];
BLNPoint *p5=[[BLNPoint alloc] initWithX:50 WithY:100];
//@{key:value}
NSDictionary *dictionary1 = @{
@"Shanghai" : p1,
@"Beijing" : p2,
@"New York" : p3,
@"Paris" : p4};
//[value,key ,nil结束]
NSMutableDictionary *dictionary2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:
p1,@"Shanghai",
p2,@"Beijing",
p3,@"New York",
p4,@"Paris",
nil];
NSLog(@"dictionary1 count: %lu", dictionary1.count);
NSLog(@"dictionary2 count: %lu", dictionary2.count);
BLNPoint* result1=[dictionary1 objectForKey:@"Beijing"];//查value是什么
BLNPoint* result2=dictionary1[@"Shanghai"];
NSLog(@"%@", result1);
NSLog(@"%@", result2);
for(NSString* key in dictionary1)
{
id object=dictionary1[key];
NSLog(@"key:%@, object:%@", key, object);
}
[dictionary2 setObject:p5 forKey:@"London"];
[dictionary2 removeObjectForKey:@"Shanghai"];
NSLog(@"dictionary2: %@", dictionary2);
}