
NSString *str = @"123";
NSString *str1 = str;
NSString *str2 = [NSString stringWithFormat:@"%d",123];
NSLog(@"%p -- %p -- %p",str,str1,str2);
NSLog(@"str == str1 : %d",str == str1);
NSLog(@"str == str2 : %d",str == str2);
NSLog(@"str isEqual str1 : %d",[str isEqual:str1]);
NSLog(@"str isEqual str2 : %d",[str isEqual:str2]);
log:
0x10d5060a8 -- 0x10d5060a8 -- 0xa000000003332313
str == str1 : 1
str == str2 : 0
str isEqual str1 : 1
str isEqual str2 : 1由此可见
-(BOOL)isEqual:(id)object;
@property (readonly) NSUInteger hash;由官方文档可知, - isEqual: 方法返回 YES ,那么 hash 必然相等; 如果 hash 相等,那么 - isEqual: 返回的不一定是 YES
首先我们定义一个Person类,其中包含name和age俩个属性,当person的name和age同时一致时,我们认为这俩个对象是同一个人
- (BOOL)isEqual:(id)object{
//判断俩个对象的指针是否相同
if (self == object) {
return YES;
//判断俩个对象所属类是否相同
}else if (![object isKindOfClass:[self class]]) {
return NO;
}
Person *per = (Person *)object;
//判断每个属性是否相同
if ([_name isEqualToString:per.name] && _age == per.age) {
return YES;
}
return NO;
}1、判断俩个对象的指针是否相同 2、判断俩个对象所属类是否相同 3、判断每个属性是否相同
-(NSUInteger)hash
#import "Person.h"
@implementation Person
-(NSUInteger)hash {
NSLog(@"%s",__func__);
return 9999;
}
@end
Person *person1 = [[Person alloc] init];
person1.name = @"abc";
person1.age = 12;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10];
[array addObject:person1];
NSLog(@"array end");
NSLog(@"----------");
NSMutableSet *set = [NSMutableSet setWithCapacity:10];
[set addObject:person1];
NSLog(@"set end");
NSLog(@"----------");
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:person1 forKey:@"user"];
NSLog(@"dic end");
NSLog(@"----------");
log:
array end
----------
-[Person hash]
set end
----------
dic end
----------NSSet添加新成员时, 需要根据hash值来快速查找成员, 以保证集合中是否已经存在该成员
hash 值的目的是尽最大可能返回一个标识,但并不是一定要是唯一的。根据 Person 的设定,能标识 Person 的是 name 和 age 属性,所以我们可以根据这两个属性来进行 hash 值的生成。
- (NSUInteger)hash {
return [_name hash] ^ _age;
} Person *person1 = [[Person alloc] init];
person1.name = @"abc";
person1.age = 12;
Person *person2 = [[Person alloc] init];
person2.name = @"def";
person2.age = 12;
NSMutableSet *set = [NSMutableSet setWithCapacity:10];
[set addObject:person1];
[set addObject:person2];
NSLog(@"before set: %@",set);
NSLog(@"before person1 hash: %ld",[person1 hash]);
NSLog(@"before person2 hash: %ld",[person2 hash])
person2.name = @"abc";
NSLog(@"after set: %@",set);
NSLog(@"after person1 hash: %ld",[person1 hash]);
NSLog(@"after person2 hash: %ld",[person2 hash]);
NSSet *lastSet = [set copy];
NSLog(@"lastSet:%@",lastSet);
log:
before set: {(
<Person: 0x60000045e420>,
<Person: 0x60000045e840>
)}
before person1 hash: 516202365
before person2 hash: 517992654
after set: {(
<Person: 0x60000045e420>,
<Person: 0x60000045e840>
)}
after person1 hash: 516202365
after person2 hash: 516202365
lastSet:{(
<Person: 0x60000044ced0>
)}在编写判定方法时,需要重写“isEqual”方法,如果对比参数与实际类属于同一类(类似isEqualToString:),那么就调用自己的判定方法,否则就交给父类判断 例如Person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) NSInteger age;
- (BOOL)isEqualToPerson:(Person *)person;
@end
#import "Person.h"
@implementation Person
- (BOOL)isEqualToPerson:(Person *)person{
if (self == person) {
return YES;
}
if ([_name isEqualToString:person.name] && _age == person.age) {
return YES;
}
return NO;
}
- (BOOL)isEqual:(id)object{
if ([[object class] isKindOfClass:[self class]]) {
return [self isEqualToPerson:object];
}else{
return [super isEqual:object];
}
}
- (NSUInteger)hash {
return [_name hash] ^ _age;
}
@endEffective+Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法