views:

316

answers:

2

Is there any downside to using NSSet as key in NSMutableDictionary, any gotchas to be aware of, any huge performance hits?

I think keys are copied in Cocoa containers, does it mean NSSet is copied to dictionary? Or is there some optimization that retains the NSSet in this case?

Related to http://stackoverflow.com/questions/1863061/can-a-nsdictionary-take-in-nsset-as-key

Example code:

NSMutableDictionary * dict = [NSMutableDictionary dictionary];

NSSet * set;
set = [NSSet setWithObjects:@"a", @"b", @"c", @"d", nil];
[dict setObject:@"1" forKey:set];

set = [NSSet setWithObjects:@"b", @"c", @"d", @"e", nil];
[dict setObject:@"2" forKey:set];

id key;
NSEnumerator * enumerator = [dict keyEnumerator];
while ((key = [enumerator nextObject]))
    NSLog(@"%@ : %@", key, [dict objectForKey:key]);

set = [NSSet setWithObjects:@"c", @"b", @"e", @"d", nil];
NSString * value = [dict objectForKey:set];
NSLog(@"set: %@ : key: %@", set, value);

Outputs:

2009-12-08 15:42:17.885 x[4989] (d, e, b, c) : 2
2009-12-08 15:42:17.887 x[4989] (d, a, b, c) : 1
2009-12-08 15:42:17.887 x[4989] set: (d, e, b, c) : key: 2
+4  A: 

I think keys are copied in Cocoa containers, does it mean NSSet is copied to dictionary? Or is there some optimization that retains the NSSet in this case?

NSDictionaries do copy their keys.

An immutable set will probably respond to copy by returning itself retained, making the “copy” practically free.

A mutable set will respond to copy by returning a copy of itself, which is why using mutable objects as keys is generally a bad idea (you won't be able to find the original after mutating it because it no longer compares equal to the key in the dictionary).

Peter Hosey
+1, yep I'm only considering immutable instances, I understand that it would be problematic to have mutable keys.
stefanB
+1  A: 

Ooh. Yes. There is a big performance downside. It happens that -[NSSet hash] is implemented as [set count]. That means that if all your sets have 2 objects, say, then they all have the same hash, and the collection will perform very poorly.

Ken