【发布时间】:2015-02-11 18:27:01
【问题描述】:
NSDictionary 键是 id
但是,您可以自己修改单个对象(如果它们支持修改)。
如果您修改一个对象,这可能会影响该对象的哈希值,从而影响查找。我假设 NSSet 是一个快速查找?
下面的例子展示了如果你改变对象,事情会如何崩溃:
NSMutableString *str = [NSMutableString stringWithString: @"AWESOME"];
NSCountedSet *countedSet = [[NSCountedSet alloc] init];
[countedSet addObject: str];
[countedSet addObject: str];
NSLog(@"%@", @([countedSet countForObject: @"AWESOME"]));
[str appendString: @" NOT AWESOME"];
NSLog(@"%@", @([countedSet countForObject: @"AWESOME NOT AWESOME"]));
NSLog(@"%@", @([countedSet countForObject: @"AWESOME"]));
NSLog(@"%@", @([countedSet countForObject: str]));
for(NSString *s in countedSet) {
NSLog(@"%@ - %@", str, @([countedSet countForObject: s]));
}
NSSet *set = [NSSet setWithArray: @[ str ]];
NSLog(@"Set Contains string, %@", @([set containsObject: str]));
[str appendString: @"asdf"];
NSLog(@"Set Contains string, %@", @([set containsObject: str]));
NSLog(@"%@", set);
并以我的解释输出:
[64844:303] 2 // Count is 2
[64844:303] 0 // Count should be 2 - if it looks for the literal string
[64844:303] 0 // Count should be 0, but can't find original object either
[64844:303] 0 // Count should be 2 - asking for actual object that's in there
[64844:303] AWESOME NOT AWESOME - 0 // Should be 2 - asking for actual object that it just retrieved
[64844:303] Set Contains string, 1 // Correct, pre-mutation
[64844:303] Set Contains string, 0 // Should be true, object is in there
[65070:303] {(
"AWESOME NOT AWESOMEasdf" // see? It's in there
)}
我的看法:
集合可能基于哈希值的桶,当哈希在集合后面被改变时,它不知道该怎么做并且查找被破坏。这方面缺乏文档。
我的问题重申: 文档说你可以改变对象,这并不直观。 变异对象会破坏集合。 什么鬼?
【问题讨论】:
-
只有当你改变参与等于和散列确定的值时,它才会破坏集合。而禁止集合元素的变异会严重限制函数的实用性。
标签: objective-c cocoa