有 2 个选择(可能更多)。以 NSSet 为例:
NSMutableSet * mutableSet = [ NSMutableSet setWithSet:nonMutableSet ] ;
或
NSMutableSet * mutableSet = [ [ nonMutableSet mutableCopy ] autorelease ] ;
这两种实现有什么区别吗?一个“更有效率”吗? (其他例子是 NSArray/NSMutableArray 和 NSDictionary/NSMutableDictionary
最佳答案
基准测试的乐趣! :)
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{ @autoreleasepool {
NSMutableSet *masterSet = [NSMutableSet set];
for (NSInteger i = 0; i < 100000; i++) {
[masterSet addObject:[NSNumber numberWithInteger:i]];
}
clock_t start = clock();
for (NSInteger i = 0; i < 100; i++) {
@autoreleasepool {
[NSMutableSet setWithSet:masterSet];
}
}
NSLog(@"a: --- %lu", clock() - start);
sleep(1);
start = clock();
for (NSInteger i = 0; i < 100; i++) {
@autoreleasepool {
[[masterSet mutableCopy] autorelease];
}
}
NSLog(@"b: --- %lu", clock() - start);
return 0;
} }
在我的机器 (10.7) 上,setWithSet: 比 -mutableCopy 慢 ~3 倍(有人想在 iOS 5 上试试吗?:))
现在,问题是:为什么?
-mutableCopy 大部分时间都花在 CFBasicHashCreateCopy() 上(参见 CFBasicHash.m )。这似乎是直接复制哈希桶,没有重新哈希。
Running Time Self Symbol Name
256.0ms 61.5% 0.0 -[NSObject mutableCopy]
256.0ms 61.5% 0.0 -[__NSCFSet mutableCopyWithZone:]
256.0ms 61.5% 0.0 CFSetCreateMutableCopy
255.0ms 61.2% 156.0 CFBasicHashCreateCopy
97.0ms 23.3% 44.0 __CFSetStandardRetainValue
-setWithSet 枚举集合中的每个值,然后将其添加到新集合中。从 CFBasicHashAddValue 的实现(再次在 CFBasicHash.m 中)来看,它似乎正在重新散列集合中的每个值。
Running Time Self Symbol Name
1605.0ms 86.0% 0.0 +[NSSet setWithSet:]
1605.0ms 86.0% 2.0 -[NSSet initWithSet:copyItems:]
1232.0ms 66.0% 68.0 -[__NSPlaceholderSet initWithObjects:count:]
1080.0ms 57.8% 299.0 CFBasicHashAddValue
324.0ms 17.3% 28.0 -[NSSet getObjects:count:]
272.0ms 14.5% 75.0 __CFBasicHashFastEnumeration
这种重新散列在 CFSet 级别是有意义的。 CFSets 在 callBacks 参数中带一个 CFSetHashCallBack;因此,两个 CFSets of CFNumbers 可以指定不同的哈希例程。 Foundation 的 NSSet 在底层使用 CFSet,并且有一个调用 -[NSObject hash]
的 CFSetHashCallBack 函数。 (虽然我猜想 Apple 可以优化这种情况并避免在两个集合具有相同的哈希回调时重新哈希)。
请注意,此基准测试仅适用于(NSNumbers 的)NSSet,其他集合类可能具有不同的性能特征。
关于ios - 制作非可变对象的可变副本的首选方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8985341/