此SO answer显示NSDictionary的散列值是字典中条目的数量。 (Similarly, the hash of an NSArray is its length。)答案继续建议创建一个类别以提供更好的散列实现。覆盖NSArray的散列值
如果您需要更准确的散列值,您可以在Obj-C类别中自己提供一个 。
但是,当我尝试这个,似乎无论如何使用原始的哈希实现。
我们在NSDictionary+Hash.m
在NSDictionary+Hash.h
#import <Foundation/Foundation.h>
@interface NSDictionary (Hash)
- (NSUInteger)hash;
@end
页眉和执行:
#import "NSDictionary+Hash.h"
@implementation NSDictionary (Hash)
- (NSUInteger)hash
{
// Based upon standard hash algorithm ~ https://stackoverflow.com/a/4393493/337735
NSUInteger result = 1;
NSUInteger prime = 31;
// Fast enumeration has an unstable ordering, so explicitly sort the keys
// https://stackoverflow.com/a/8529761/337735
for (id key in [[self allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
id value = [self objectForKey:key];
// okay, so copying Java's hashCode a bit:
// http://docs.oracle.com/javase/6/docs/api/java/util/Map.Entry.html#hashCode()
result = prime * result + ([key hash]^[value hash]);
}
return result;
}
一个简单的单元测试显示了原始的实现是在使用中:
#import "NSDictionary+Hash.h"
#import <SenTestingKit/SenTestingKit.h>
@interface NSDictionary_HashTest : SenTestCase
@end
@implementation NSDictionary_HashTest
- (void)testHash
{
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"val1", @"key1", @"val2", @"key2", nil];
NSUInteger result = 1;
result = 31 * result + ([@"key1" hash]^[@"val1" hash]);
result = 31 * result + ([@"key2" hash]^[@"val2" hash]);
STAssertEquals([dict hash], result, nil);
}
@end
这测试失败,“2”应该等于“2949297985”。
现在,如果我在类别标题和实现文件中将方法从哈希重命名为hashy(例如),那么[dict hashy]
会返回正确的值。是否可以重写某个类别中的“内置”方法?我在做别的事吗?
科迪,你绝对可以用类别覆盖内建的方法。 – xyzzycoder
它曾经是这种情况,我不确定当前的情况,如果你有两个实现了相同方法名的类,并且这两个类都是单个类的一部分,那么链接顺序决定了哪个方法会被调用由运行时。 Objective-C在过去五年中发生了很大变化,所以现在这种行为可能会有所不同。 – xyzzycoder