先创建一个类CHHPerson作为测试类
CHHPerson.h
#import <Foundation/Foundation.h>
@interface CHHPerson : NSObject
@property (nonatomic,copy) NSString *firstName;
@property (nonatomic,copy) NSString *lastName;
@property (nonatomic,assign) int age;
-(id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName age:(int)age;
-(BOOL)isEqualToPerson:(CHHPerson *) person;
@end
CHHPerson.m
#import "CHHPerson.h"
@implementation CHHPerson
static kBuildCount = 0;
-(id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName age:(int) age
{
self = [super init];
if(self) {
_firstName = [firstName copy];
_lastName = [lastName copy];
_age = age;
}
return self;
}
-(BOOL)isEqualToPerson:(CHHPerson *)person
{
if(person == self)
{
return true;
}
if(![_firstName isEqualToString:person.firstName])
{
return false;
}
if(![_lastName isEqualToString:person.lastName])
{
return false;
}
if(_age != person.age)
{
return false;
}
return true;
}
/// 2个对象判断相等关键还是 isEqual
- (BOOL)isEqual:(id)other
{
if ([other class] == [self class]) {
return [self isEqualToPerson:(CHHPerson *) other];
} else {
return [super isEqual:other];
}
}
/// 为hash table 所用 , 其对应的isEqual 用到这个值
- (NSUInteger)hash
{
return ++kBuildCount;
//return 1;
}
@end
== 判断为同一个对象(指针地址判断)
测试代码:
NSObject * objectA = [NSObject new];
NSObject * objectB = [NSObject new];
NSObject * objectAA = objectA;
NSLog(@"objectA == objectB : %d",(objectA == objectB));
NSLog(@"objectA == objectAA : %d",(objectA == objectAA));
输出结果:
2017-03-15 23:04:34.017969 Effective_9[18875:11149290] objectA == objectB : 0
2017-03-15 23:04:34.018281 Effective_9[18875:11149290] objectA == objectAA : 1
isEqual 判断
单个对象之间的对比
isEqual返回true 和 hash值一样
修改CHHPerson.m 中 hash 方法返回1
- (NSUInteger)hash
{
//return ++kBuildCount;
return 1;
}
两个对象对比:
CHHPerson * personA = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"A" age:13];
CHHPerson* personB = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"A" age:13];
NSLog(@"personA isEqual personB : %d",([personA isEqual:personB]));
输出结果: 2对象相等
2017-03-16 09:25:24.654742 Effective_9[19008:11167812] personA isEqual personB : 1
isEqual返回true 和 hash值不同
修改CHHPerson.m 中 hash 方法返回
- (NSUInteger)hash
{
return ++kBuildCount;
//return 1;
}
同上测试输出结果: 2对象相等
2017-03-16 10:52:14.926642 Effective_9[19261:11223212] personA isEqual personB : 1
单个对象中间用isEqual的结果和hash值无关
那hash值什么时候用到呢?--》集合
如果一个被插入集合类的可变对象是依据其 hash 值来决定其在集合中的位置的话,这个对象的 hash 函数所返回的值在该对象存在于集合中时是不允许改变的。所以以下的测试时当时小白时的笑话~~~
集合对比
Set对比
修改CHHPerson.m 中 hash 方法返回不同值
为了查看打印了那个对象,注释掉lastName在isEqualToPerson中的对比,在hash中打印lastName
** set中只存在1个对象**
测试代码:
CHHPerson * personA = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"A" age:13];
NSMutableSet * set = [NSMutableSet new];
[set addObject:personA];
CHHPerson * personC = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"C" age:13];
NSMutableSet * set2 = [NSMutableSet new];
[set2 addObject:personC];
NSLog(@"set isEqual set2 start");
NSLog(@"set isEqual set2 : %d",([set isEqual:set2]));
输出结果:2个set相等
2017-03-16 11:25:09.377660 Effective_9[19546:11246836] CHHPerson get hash A
2017-03-16 11:25:09.378474 Effective_9[19546:11246836] CHHPerson get hash A
2017-03-16 11:25:09.378509 Effective_9[19546:11246836] CHHPerson get hash C
2017-03-16 11:25:09.378531 Effective_9[19546:11246836] CHHPerson get hash C
2017-03-16 11:25:09.378543 Effective_9[19546:11246836] set isEqual set2 start
2017-03-16 11:25:09.378603 Effective_9[19546:11246836] CHHPerson get hash A
2017-03-16 11:25:09.378619 Effective_9[19546:11246836] CHHPerson get hash A
2017-03-16 11:25:09.378633 Effective_9[19546:11246836] set isEqual set2 : 1
出乎意料:2个person的hash值不同,2个set竟然相等
查看log可以看出,在set对比时,set是调用了对象的hash方法,但是都是调用personA。
** set中再添加1个对象**
测试代码:
CHHPerson * personA = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"A" age:13];
CHHPerson* personB = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"B" age:15];
NSMutableSet * set = [NSMutableSet new];
[set addObject:personA];
[set addObject:personB];
CHHPerson * personC = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"C" age:13];
CHHPerson* personD = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"D" age:15];
NSMutableSet * set2 = [NSMutableSet new];
[set2 addObject:personC];
[set2 addObject:personD];
NSLog(@"set isEqual set2 start");
NSLog(@"set isEqual set2 : %d",([set isEqual:set2]));
输出结果: 2个set终于不相等了
2017-03-16 11:30:42.348644 Effective_9[19602:11250347] CHHPerson get hash A
2017-03-16 11:30:42.348816 Effective_9[19602:11250347] CHHPerson get hash A
2017-03-16 11:30:42.348841 Effective_9[19602:11250347] CHHPerson get hash B
2017-03-16 11:30:42.348867 Effective_9[19602:11250347] CHHPerson get hash C
2017-03-16 11:30:42.348882 Effective_9[19602:11250347] CHHPerson get hash C
2017-03-16 11:30:42.348896 Effective_9[19602:11250347] CHHPerson get hash D
2017-03-16 11:30:42.348934 Effective_9[19602:11250347] set isEqual set2 start
2017-03-16 11:30:42.348978 Effective_9[19602:11250347] CHHPerson get hash B
2017-03-16 11:30:42.348991 Effective_9[19602:11250347] CHHPerson get hash B
2017-03-16 11:30:42.349014 Effective_9[19602:11250347] set isEqual set2 : 0
注意:
虽然2个set不相等了,但在对比时也是只调用了personB的hash方法。
结(个人猜测):当set中只用1个对象时,isEqual对比和对象的hash值无关,当大于1个对象时才用到对象的hash值
hash 方法返回相同值
** set中2个对象**
输出结果:2个set相等
2017-03-16 11:36:43.732768 Effective_9[19618:11253370] CHHPerson get hash A
2017-03-16 11:36:43.734181 Effective_9[19618:11253370] CHHPerson get hash A
2017-03-16 11:36:43.734215 Effective_9[19618:11253370] CHHPerson get hash B
2017-03-16 11:36:43.734496 Effective_9[19618:11253370] CHHPerson get hash C
2017-03-16 11:36:43.734519 Effective_9[19618:11253370] CHHPerson get hash C
2017-03-16 11:36:43.734537 Effective_9[19618:11253370] CHHPerson get hash D
2017-03-16 11:36:43.734557 Effective_9[19618:11253370] set isEqual set2 start
2017-03-16 11:36:43.734597 Effective_9[19618:11253370] CHHPerson get hash A
2017-03-16 11:36:43.734614 Effective_9[19618:11253370] CHHPerson get hash A
2017-03-16 11:36:43.734623 Effective_9[19618:11253370] CHHPerson get hash B
2017-03-16 11:36:43.734631 Effective_9[19618:11253370] CHHPerson get hash B
2017-03-16 11:36:43.734642 Effective_9[19618:11253370] set isEqual set2 : 1
注意:
虽然2个set相等了,但在对比时也是只调用了personA和 personB的hash方法。
set对比结果:
(个人猜测)
当set中对象个数对应1时,set的isEqual对比时,和对象的isEqual返回有关和hash无关(存疑);当set中对象个数大于1时,set的isEqual对比时,和对象的isEqual和hash返回都有关
但set对比时hash的获取存在问题,求大神指导
NSArray 对比
isEqual返回true 和 hash值不同
测试代码:
CHHPerson * personA = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"A" age:13];
CHHPerson* personB = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"B" age:15];
NSArray *arr = @[personA,personB];
CHHPerson * personC = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"C" age:13];
CHHPerson* personD = [[CHHPerson alloc] initWithFirstName:@"A" lastName:@"D" age:15];
NSArray *arr2 = @[personC,personD];
NSLog(@"arr isEqual arr2 start");
NSLog(@"arr isEqual arr2 : %d",([arr isEqualToArray:arr2]));
输出结果: 2个Array相等
2017-03-16 11:57:09.848158 Effective_9[19713:11268253] arr isEqual arr2 start
2017-03-16 11:57:09.848736 Effective_9[19713:11268253] arr isEqual arr2 : 1
NSArray 对比结果:
和hash无关,但是和数组排列顺序是有关的
小结:
1.hash方法是为那些需要用到 hashtable 的集合服务的(当然你也可以再isEqual中加入hash值的对比)
2.当set中对象个数对应1时,set的isEqual对比时,和对象的isEqual返回有关和hash无关(存疑);当set中对象个数大于1时,set的isEqual对比时,和对象的isEqual和hash返回都有关
3.NSArray对比时,对象的isEqual和排列顺序有关,和hash无关
4.== 只是判断同一个地址
疑惑
set对比时,对象hash获取的顺序问题,和对比方式