参考
http://stackoverflow.com/questions/29491141/about-isequal-and-hash
isEqual:
This method defines what it means for instances to be equal. For example, a container object might define two containers as equal if their corresponding objects all respond YES
to an isEqual:
request. See the NSData
,NSDictionary
, NSArray
, and NSString
class specifications for examples of the use of this method.
If two objects are equal, they must have the same hash value. This last point is particularly important if you define isEqual:
in a subclass and intend to put instances of that subclass into a collection. Make sure you also define hash
in your subclass.
假如两个对象相等,那么它们必拥有相同的hash值,这点十分重要。如果你在子类中定义了isEqual方法并且打算将该子类的实例放入集合中,那么相等对象拥有相同的hash就十分重要。确保你在子类中定义了hash方法。
hash
If two objects are equal (as determined by the isEqual:
method), they must have the same hash value. This last point is particularly important if you define hash
in a subclass and intend to put instances of that subclass into a collection.
如果两个对象相等(像isEqual:方法定义的那样),那么它们一定拥有相同的hash值(如果两个对象的hash值相同的话,它们有可能不相等)。如果你在子类中定义了hash并且打算将实例添加到集合中,那么谨记这一点十分重要。
If a mutable object is added to a collection that uses hash values to determine the object’s position in the collection, the value returned by the hash
method of the object must not change while the object is in the collection. Therefore, either the hash
method must not rely on any of the object’s internal state information or you must make sure the object’s internal state information does not change while the object is in the collection. Thus, for example, a mutable dictionary can be put in a hash table but you must not change it while it is in there. (Note that it can be difficult to know whether or not a given object is in a collection.)
如果一个可变对象被添加到了一个集合中,并且使用了hash值来决定对象在集合中的位置,那么处于集合中的对象的hash方法返回的数值一定不能变。既然如此,要么hash方法不依赖于对象的内在状态信息,要么你必需保证对象在集中时,内在信息不会被改变。例如,一个可变的dictionary可以被放入一个hash表中,但是只要dictionary存在于hash表中,你就不能改变它的值。(谨记,很难判断一个给定对象是否在集合中)。
在判断两个对象是否相等时最好调用相应对象具体的比较方法,而不是NSObject的isEqual方法,如:
NSData isEqualToData:
NSDictionary isEqualToDictionary:
NSArrayisEqualToArray:
NSStringisEqualToString:
因为这些方法更加准确,并且做了一些优化,集合进行判等时可能不会调用到isEqual:方法
例如:
NSMutableArray *arr1 = [NSMutableArray arrayWithCapacity:3];
NSMutableArray *arr2 = [NSMutableArray arrayWithCapacity:3];
NSMutableArray *arr3 = [NSMutableArray arrayWithCapacity:3];
for (int i = 0; i < 3; i++) {
TestCopy *temp = [[TestCopy alloc] init];
[arr1 addObject:temp];
[arr2 addObject:temp];
}
for (int i = 0; i < 3; i++) {
TestCopy *temp = [[TestCopy alloc] init];
[arr3 addObject:temp];
}
NSLog(@"isEqual:%d",[arr1 isEqualToArray:arr2]);<span style="white-space:pre"> </span>//line 1
NSLog(@"isEqual:%d", [arr1 isEqualToArray:arr3]);<span style="white-space:pre"> </span>//line 2
其中TestCopy重写了isEqual:方法和hash方法
进行line1中的比较时,没有调用到TestCopy中的isEqual: 方法
进行line2中的比较时,调用到了TestCopy中的isEqual: 方法
推测 NSArray 的 isEqualToArray方法先进行了 contentObject1 == contentObject2比较,如果不等才调用contentObject 的isEqual:方法