[Foundation]框架--字典

字典
在这里插入图片描述
1. NSDictionary的功能与用法

我们OC中提供了类方法与实例方法来创造我们的字典,两种方法传入的参数基本类似,只是类方法以dictionary开始,实例方法以init开头。
下面是创建NSDictionary的方法:
在这里插入图片描述
得到对象后就可以通过下列方法来访问集合中key和value:
在这里插入图片描述
在这里插入图片描述
下面将会示范NSDictionary的两个基本用法,程序可以通过快速枚举来遍历NSDictionary的所有key。除此之外,程序也可以根据key来获取NSDictionary中对应的value。
通过key来获取value有如下两种语法:
1.调用NSDictionary的objectForKey来获取相对应的value;
2.直接使用下标法根据key来获取对应的value;

[dictionary objectForKey: key];
 dictionary[key];

接口部分:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSDictionary (print)
- (void) print;
@end

NS_ASSUME_NONNULL_END


#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FKUser : NSObject
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* pass;
- (id) initWithName: (NSString* ) name pass: (NSString* ) pass;
- (void) say: (NSString* ) content;
@end

NS_ASSUME_NONNULL_END

实现部分:

#import "NSDictionary+print.h"

@implementation NSDictionary (print)

- (void)print {
    NSMutableString* result = [NSMutableString stringWithString:@"["];
    //
    //
    for (id key in self) {
        [result appendString: [key description]];
        [result appendString: @"="];
        //
        [result appendString:[self [key] description]];
        [result appendString:@", "];
    }
    //获取字符串长度
    NSUInteger len = [result length];
    //
    [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
    [result appendString:@"]"];
    NSLog(@"%@", result);
}
@end


#import "FKUser.h"
@implementation FKUser
@synthesize name;
@synthesize pass;
- (id)initWithName:(nonnull NSString *) aname pass:(nonnull NSString *) apass {
    if (self == [super init]) {
        self.name = aname;
        self.pass = apass;
    }
    return self;
}
- (void)say:(nonnull NSString *)content {
    NSLog(@"%@说:%@", self.name, content);
}
//重写isEqual:方法,重写方法的标准是如果两个FKUser的name, pass相等,即可认为他们相等。
- (BOOL) isEqual:(id) other {
    if (self == other) {
        return YES;
    }
    if ([other class] == FKUser.class) {
        FKUser* target = (FKUser* ) other;
        return [self.name isEqual:target.name] &&[self.pass isEqual:target.pass];
    }
    return NO;
}
//重写description方法,可以直接看到FKUser对象的状态
- (NSString*) description {
    return [NSString stringWithFormat:@"<FKUser[name = %@, pass = %@]>", self.name, self.pass];
}
//重写Hash方法,从写该方法的标准为如果两个FKUser的name,pass相等,两个FKUser的Hash方法返回值相等
- (NSUInteger) hash {
    NSLog(@"===hash===");
    NSUInteger nameHash = name == nil ? 0 : [name hash];
    NSUInteger passHash = pass == nil ? 0 : [pass hash];
    return nameHash*31 + passHash;
}
@end

主函数:

#import <Foundation/Foundation.h>
#import "FKUser.h"
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //直接使用多个value,key的形式创建NSDictionary对象
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                              [[FKUser alloc] initWithName:@"lai" pass:@"123"], @"one",
                              [[FKUser alloc] initWithName:@"gao" pass:@"345"], @"two",
                              [[FKUser alloc] initWithName:@"zhu" pass:@"123"], @"three",
                              [[FKUser alloc] initWithName:@"cui" pass:@"178"], @"four",
                              [[FKUser alloc] initWithName:@"li" pass:@"155"], @"five",
                              nil];
        [dict print];
        NSLog(@"dict包含%ld个key—value对", [dict count]);
        NSLog(@"dict中所有的的key为:%@", [dict allKeys]);
        NSLog(@"<FKUser [name = sun, pass = 123>对应的所有key", [dict allKeysForObject:[[FKUser alloc] initWithName:@"lai" pass:@"123"]]);
        //获取遍历dict所有value的枚举器
        NSEnumerator* en = [dict objectEnumerator];
        NSObject* value;
        //使用枚举器来遍历dict所有value
        while (value = [en nextObject]) {
            NSLog(@"%@", value);
        }
        //使用指定代码块来迭代执行该集合中所有key-value
        [dict enumerateKeysAndObjectsUsingBlock:
         //该集合包含多个key- value对,下面打代码块就执行相应的次数
         ^(id key, id value, BOOL* stop) {
            NSLog(@"key的值为:%@", key);
            [value say: @"疯狂iOS讲义"];
        }];
    }
    return 0;
}

代码运行结果如下:
在这里插入图片描述

2.对NSDictionary的key排序
NSDictionary还提供了方法对NSDictionary的所有key执行排序,这些方法执行完成后返回排序完成后的所有key组成的NSSArray。NSDictionary提供的排序方法如下:
在这里插入图片描述
下面展示代码部分:

#import <Foundation/Foundation.h>
#import "FKUser.h"
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //直接使用多个value,key的形式创建NSDictionary对象
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                              @"Object-C", @"one",
                              @"Ruby", @"two",
                              @"Python", @"three",
                              @"Perl", @"four",
                              nil];
        //打印dict集合中的所有元素
        [dict print];
        //获取所有直接调用value的compare:方法对所有的key进行排序
        //返回排好序的所有的key组成的NSArray
        NSArray* keyArr1 = [dict keysSortedByValueUsingSelector:@selector(compare:)];
        NSLog(@"%@", keyArr1);
        NSArray* keyArr2 = [dict keysSortedByValueUsingComparator:
                            //对NSDictionary的value进行比较,字符串越长即可认为该value越大
                            ^(id value1, id value2) {
            //下面定义比较小的标准字符串越长即可认为该value越大
            if ([value1 length] > [value2 length]) {
                return NSOrderedDescending;
            }
            if ([value1 length] < [value2 length]) {
                return NSOrderedAscending;
            }
            return  NSOrderedSame;
        }];
        NSLog(@"%@", keyArr2);
    }
    return 0;
}

代码运行结果如下:
在这里插入图片描述
3.对NSDictionary的key进行过滤
NSDictionary还提供了方法对NSDictionary的所有key执行过滤,这些方法执行完成后返回满足条件的key组成的NSSet。NSDictionary提供了如下过滤方法:
在这里插入图片描述
如下代码所示:

#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       //直接使用多个value,key的形式来创建NSDictionary对象
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSNumber numberWithInt: 89], @"Object-C",
                              [NSNumber numberWithInt: 69], @"Ruby",
                              [NSNumber numberWithInt: 75], @"Python",
                              [NSNumber numberWithInt: 109], @"Perl",
                              nil];
        //打印dict的集合元素
        [dict print];
        //对NSDictionary所有key进行过滤
        NSSet* keyset = [dict keysOfEntriesPassingTest:
        //对NSDictionary的value进行比较,字符串越长即可认为该value越大
            ^(id key, id value, BOOL *stop ) {
            //当value的值大于80时返回YES
            //这意味着只有value的值大于80的key才会被保留下来
            return (BOOL) ([value intValue] > 80);
        }];
        NSLog (@"%@", keyset);
    }
    return 0;
}

代码运行结果如下:
在这里插入图片描述
4.使用自定义类作为NSDictionary的key
我们前面介绍我们的key时一般都是使用我们的NSString作为我们的key
如果我们的程序打算使用自定义类来作为我们的NSDictionary的key
我们的正确重写分为以下两步:

  1. 我们的自定义类正确重写过我们的我们的isEqual以及hash方法,保证当isEqual判断相等时我们的程序返回的hash值也是相等的
  2. 我们的自定义类必须实现了copyWithZone方法且最好能返回我们的不可变副本。

在这里我们需要解释一下我们为什么需要实现这个方法:
因为我们的key在我们的字典中是非常关键的,出于安全性考虑,我们的key一般是不能改变的。如果我们key本身是可变的,且程序可以通过其他变量来修改key,那么这是非常不好的
为了避免这种情况,所以我们要保证只要程序把任何对象作为key放入我们的字典,我们的字典总会先调用该key的copy方法来复制该对象的不可变副本,然后以该副本作为字典的key,这样就保证了我们的key没有办法被修改。
为了让我们的自定义的类作为key,我们还需要让我们的自定义类实现NSCopying协议,并让该类实现copyWithZone方法。
下面是代码部分:
实现部分:

- (id) copywithZone: (NSZone* )zone {
    NSLog(@"--正在复制--");
    //
    FKUser* newUser = [[[self class] allocWithZone:zone] init];
    //
    newUser->name = name;
    newUser->pass = pass;
    return newUser;
}

主函数:

#import <Foundation/Foundation.h>
#import "FKUser.h"
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        FKUser* u1 = [[FKUser alloc] initWithName:@"lai" pass:@"345"];
        //直接使用多个value,key的形式来创建NSDictionary对象
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                              @"one", [[FKUser alloc] initWithName:@"gao" pass:@"123"],
                              @"two", u1,
                              @"three", [[FKUser alloc] initWithName:@"gao" pass:@"123"],
                              @"four", [[FKUser alloc] initWithName:@"li" pass:@"178"],
                              @"five", [[FKUser alloc] initWithName:@"gao" pass:@"155"],
                              nil];
        u1.pass = nil;
        //由于NSDictionary并为直接使用u1指向FKUser作为key
        //而是先复制u1所指向的对象的副本,然后以该副本作为key
        //以此程序将可以看到dict的key不受任何影响
        [dict print];
    }
    return 0;
}

我们上述的程序按value1,key1的格式来设置我们的字典。我们的程序有多对value-key。然后在前面知道了,当程序尝试使用任何对象来作为我们的key时,我们的key都会先调用copy方法来复制该key的不可变副本,这也是我们需要实现copyWithZone:方法的原因。然后我们的程序实际上是将该副本作为我们NSDictionary的key。因此无论我们怎么修改我们的key,他都不会出现变化。
5.NSMutableDictionary的功能和用法
由于该类可以动态的添加key-value对,所以创建该集合时可以指定初始容量。
在这里插入图片描述
下面可以通过代码来进一步了解:

#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //直接使用多个value,key的形式来创建NSDictionary对象
       NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithInt: 89], @"疯狂iOS讲义"
                                    , nil];
        //使用下标法设置key-value对。由于NSDictionary已经存在该key
        //因此此处设置会覆盖掉鱼啊来的value
        dict [@"疯狂iOS讲义"] = [NSNumber numberWithInt: 99];
        [dict print];
        NSLog(@"---再次添加key-value对---");
        dict[@"疯狂XLM讲义"] = [NSNumber numberWithInt: 69];
        [dict print];
        NSDictionary* dict2 = [NSDictionary dictionaryWithObjectsAndKeys:
                               [NSNumber numberWithInt: 79], @"疯狂Ajax讲义",
                               [NSNumber numberWithInt: 89], @"Struts 2.x权威指南",
                                nil];
        //将另一个NSDictionary中的key-value对添加到当前NSDictionary中
        [dict addEntriesFromDictionary: dict2];
        [dict print];
        //根据key来删除key-value对
        [dict removeObjectForKey:@"Struts 2.x权威指南"];
        [dict print];
    }
    return 0;
}

代码运行结果如下:
在这里插入图片描述
结合上面程序中粗体字代码对NSMutableDictionary中的key-value对的改变,以及上面的输出结果,即可非常容易地体会到NSMutableDictionary中对于key-value对的改变。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值