There are 2 choices (possibly more). Using NSSet as an example:
NSMutableSet * mutableSet = [ NSMutableSet setWithSet:nonMutableSet ] ;
or
NSMutableSet * mutableSet = [ [ nonMutableSet mutableCopy ] autorelease ] ;
Is there any difference between these two implementations? Is one “more efficient” at all? (Other examples would be NSArray/NSMutableArray and NSDictionary/NSMutableDictionary
Benchmark fun! 🙂
On my machine (10.7), setWithSet: is ~3x slower than -mutableCopy (Does somebody want to try on iOS 5? 🙂 )
Now, the question is: why?
-mutableCopy is spending most of its time in CFBasicHashCreateCopy() (see CFBasicHash.m). This appears to be copying the hash buckets directly, with no rehashing.
-setWithSet is enumerating through each value of the set, and then adding it to the new set. From the implementation of CFBasicHashAddValue (again in CFBasicHash.m), it looks like it is rehashing each value in the set.
This rehash makes sense at the CFSet level. CFSets take a CFSetHashCallBack in the callBacks parameter; thus, two CFSets of CFNumbers could have a different hashing routine specified. Foundation’s NSSet uses CFSet under-the-hood, and has a CFSetHashCallBack function which invokes
-[NSObject hash]. (Although I guess that Apple could optimize this case and avoid the rehash when two sets have the same hash callback).Note that this benchmark is for NSSet (of NSNumbers) only, other collection classes may have different performance characteristics.