集合是如何判定对象相等的呢 ? - AlvinSunny/OC-TheUnderlying GitHub Wiki

Mattt大神聊Equality

iOS 中常见集合类型有NSArrayNSDictionaryNSSetNSHashTableNSMapTableNSPointerArray

在编程语言中一般都会有提供判断两个"元素"是否相等的手段,比较通用的就是 ==, 其次就是api比如iOS中的isEqual:命名可能不同但作用都是一样的

==: 判断的方式是通过内存地址对比,内存地址相同即为同一个元素

isEqual:: 基类(NSObject)的内部实现 return anObject == self,但是如集合会有不同

objc4-818.2 Object.mm 源码


  Returns whether the receiver is equal to the argument. //返回接收器是否等于实参
  Defining equality is complex, so be careful when implementing this method. //定义平等是复杂,所以在实现这个方法时要小心

  Collections such as NSSet depend on the behaviour of this method. 
  In particular, this method must be commutative, so for any objects a and b: [a isEqual: b] == [b isEqual: a]
  This means that you must be very careful when returning YES if the argument is of another class.  
  像NSSet这样的集合依赖于这个方法的行为,特别这个方法是可以交换判断的,因此对于任何对象 a和b: [a isEqual: b] == [b isEqual: a]
  这意味着如果参数是另一个类,在返回YES时必须非常小心。

 For example, if you define a number class that returns YES if the argument is a string representation of the number
 then this will break because the string will not recognise your object as being equal to itself.
 如果你定义了一个返回YES的number类,如果参数是数字的字符串表示,那么这将会中断,因为字符串将不识别你的对象等于它自己
 
 If two objects are equal, then they must have the same hash value, however
 equal hash values do not imply equality. 
 如果两个对象相等,那么它们必须具有相同的哈希值,相等的哈希值并不意味着相等。

- (BOOL)isEqual: (id)anObject;

- (BOOL)isEqual:anObject {
  return anObject == self; 
}

基类(NSObject) isEqual:方法的作用是可以帮助我们判断两个对象是否相等,同时子类也可以重写该方法实现自己的定制化操作,通过自己的标准来处理(比如通过判断传入对象的某一个属性是否和自己的属性值相同来决定是否返回YES)

例如

- (BOOL)isEqual:(Persion *)object {
    [super isEqual:object];
    
    if(object==nil) return NO;
    
    if(![super isEqual:object]) return NO;
    
    if(![self isKindOfClass:[Persion class]]) return NO;
    
    if([object.name isEqualToString:self.name]) return YES;
    
    return NO;
    
}

NSArray

NSDictionary

NSSet

NSHashTable

NSMapTable

NSPointerArray