重载hash与isEqual:方法

前言

NSObject 自带了hash与isEqual:方法,服务于具有hash表结构的数据结构。NSObject自带的hash函数相当于hash表中的f(key)函数中的key,这“唯一”的key需要用户自己产生,至于用什么算法由用户自己决定。

准备

//
//  Model.h
//  Hash
//
//  Created by YouXianMing on 16/4/15.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Model : NSObject <NSCopying>

@property (nonatomic, strong) NSString  *firstName;
@property (nonatomic, strong) NSString  *lastName;

@end
//
//  Model.m
//  Hash
//
//  Created by YouXianMing on 16/4/15.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "Model.h"

#define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
#define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch)))

@implementation Model

- (id)copyWithZone:(nullable NSZone *)zone {

    Model *result = [[[self class] allocWithZone:zone] init];

    result.firstName = self.firstName;
    result.lastName  = self.lastName;

    return result;
}

- (NSUInteger)hash {

    return NSUINTROTATE([_firstName hash], NSUINT_BIT / 2) ^ [_lastName hash];
}

- (BOOL)isEqual:(id)object {

    if (self == object) {

        return YES;
    }

    if ([object isKindOfClass:[Model class]]) {

        return [self hash] == [object hash];

    } else {

        return NO;
    }
}

@end

测试

1. 测试对象是否相同(注意打印信息)

之所以会相同是因为两个对象的hash算法以属性值的唯一性来确保对象的差异性,也就是说,只要两个对象属性值一致,那这两个对象的就是相等的。

2. 测试字典setObject:forKey:方法(注意打印信息)

字典通过modelB对象作key值竟然找到了modelA作为key值时存储的值,这是因为我们已经让modelA与modelB“相等了”,可以参考测试1。

字典在设置key值的时候是需要复制这个key值对象的(这个key值对象需要实现NSCopying协议),也就是说,我们的modelA在作为key值的时候已经被字典复制一份了,因为字典需要确保这个key值不可变,否则,做为key值的对象通过修改内部属性而导致了这个对象的hash值发生变化,会出现找不到对象的情况。

大家可以观察一下断点流程(字典先获取外部对象的hash值,然后与自己的key值对象进行比较执行isEqual:方法,如果认为比较结果一致,就确保是同一个对象)

字典在执行setObject:forKey:方法的时候,会先执行这个key值对象的hash方法用以生成一个键值,然后再copy这个key值对象。

3. 测试NSSet的addObject:方法(注意打印信息)

addObject:方法执行的流程如下:先获取对象modelA的hash值,再添加modelB的时候获取modelB的hash值,然后进行比较,如果两者的比较结果一致,则认为这是相同的对象。

时间: 2024-08-10 02:04:40

重载hash与isEqual:方法的相关文章

NSDictionary实现原理-ios哈希hash和isEqual

NSDictionary实现原理-ios哈希hash和isEqual OC中自定义类的NSCopying实现的注意事项(isEqual & hash实现) http://blog.csdn.net/linshaolie/article/details/41494303 iOS开发 之 不要告诉我你真的懂isEqual与hash! http://m.blog.csdn.net/hx_lei/article/details/53885798 http://www.jianshu.com/p/9153

java中的方法重载与重写以及方法修饰符

1. 方法重载Overloading , 是在一个类中,有多个方法,这些方法的名字相同,但是具有不同的参数列表,和返回值 重载的时候,方法名要一样,但是参数类型和参数个数不一样,返回值类型可以相同,也可以不同, 不能以返回值类型判断方法是否重载. 2. 方法重写Overriding , 是存在于父类与子类之间 (1)若子类中的方法与父类中的某一方法具有相同的方法名.返回类型和参数表,则新方法覆盖父类中的方法,如需调 用父类方法用super关键字 (2)子类的重写方法的权限修饰符不能小于父类的,要

__slots__和运算符重载中的反向方法

问题的引出 都是字典惹的祸 字典为了提升查询效率,必须用空间换时间. 一般来说一个多想,属性多一点,都存储在字典中便于查询,问题不大. 但是如果数百万个对象,那么字典占的就有点大了. 这个时候,能不能把属性字典__dict__省了? python提供了__slots__ class A: x = 1 def __init__(self): self.y = 5 self.z = 6 def show(self): print(self.x,self.y,self.z) a = A() print

HashMap解决hash冲突的方法

源码分析 HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置.当程序执行 map.put(String,Obect)方法 时,系统将调用String的 hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法,都可通过该方法获得它的 hashCode 值.得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置.源码如下: public V put(K key, V value)

重载、重写、方法相同

首先一个方法对外暴露的信息有以下几个-- 权限.是否静态.是否final.返回类型.方法签名.异常类型. 其中,按照Effective Java中的约定,方法签名包括了方法名和参数列表. 重写指的是父类中的方法无法满足子类的需求,子类通过重写一个方法的方式来覆盖父类的方法. 而重写方法的某个信息需要与被重写方法的那个信息一致,才能让编译器知道,方法重写发生了. 那个是信息就是方法签名,子类的方法会去重写(override)父类中与其方法签名一致的方法, 方法签名一致,指的是方法名一致且参数类型.

Java重载重写与实现方法的规则

这几天在实训过程中做到了一个题,这个题目问的是 非抽象类实现接口后,必须实现接口中的所有抽象方法,除了abstract外,方法头必须完全一致.这句话是错误的.然后在做错以后自己总结一下重载 重写 和实现的几个点. 重载:方法名一致即可,访问修饰符.返回值类型无关,然后不同的重载方法参数列表的参数的顺序,类型,数量进行变换即可. 重写:重写方法的访问修饰符可以不同,但访问权限需要比父类中的大,比如protected修饰的方法重写的时候可以重写为public类型.返回值类型可以是父类中方法返回值类型

OC 重写description,isEqual方法

// 为了能用%@打印出对象的有效信息,需要重写description方法 - (NSString *)description { // 最简单的办法是将属性和值组合成键值对存放到字典中 // 这样只需要调用字典的description方法就能获取对应的描述字符串 NSDictionary *dictionary = @{@"name" : name_, @"address" : address_, @"friends" : friends_};

解决hash冲突的方法

通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题.创建哈希表和查找哈希表都会遇到冲突,两种情况下解决冲突的方法应该一致.下面以创建哈希表为例,说明解决冲突的方法.常用的解决冲突方法有以下四种: 1.开放定址法 这种方法也称再散列法,其基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,-,直到找出一个不冲突的哈希地址pi ,将相应元素存入

【2017-04-16】抽象类、接口、构造函数、重载、静态成员和方法

抽象类 关键字:abstract 什么是抽象类:不是实际存在的,抽象的 抽象类只能被继承,不能被实例化成对象 抽象方法一定在抽象类中,抽象类中不一定全是抽象方法,也有普通存在方法 如果要调用抽象类中的普通方法,那么需要子类继承之后实例化再调用 实际应用: public abstract class ren { public abstract string chifan() } 抽象方法没有函数体 在子类中实现: public override string chifan() { return "