Does NSSet's containsObject: test for pointer equality or value equality?
10,476
-containsObject:
uses -isEqual:
(and -hash
) for equality testing. This applies to -removeObject:
as well, and any other operations in NSSet
that depend on some notion of equality.
Comments
-
Chris almost 2 years
Say I have an
NSSet
with a string in it. If I sendcontainsObject:
with another string which is a different pointer but the exact same string value, will that returnYES
?Also, is it the same story when it comes to
removeObject:
? I.e., different objects with different pointers but the same string values will cause removal? -
Jeff Laing over 12 yearsWhere is this documented? From what I can see, CFSet is clear that it uses POINTER equality by default, but I don't see NSSet clarifying what it uses?
-
jscs over 12 years@user: The
-[NSSet member:]
documentation says that it usesisEqual:
;member
is one of the fundamental set methods, and it seems to be implied (though, you're right, not explicit) thatcontainsObject:
usesmember
. -
Lily Ballard over 12 years@user256413: All NSSet method that rely on equality must, by definition, use the same equality test. CFSet will use the pointer equality if you don't specify another equality function. If you use
kCFTypeSetCallBacks
then it usesCFEqual()
as the equality comparison. -
Chris over 12 yearsThanks, i was hoping that it used isEqual. Thanks for clearing that up
-
jowie almost 10 yearsCan someone please explain this (apologies for the formatting):
NSMutableString *str = [NSMutableString stringWithString:@"Hello"];
NSSet *set = [NSSet setWithObject:str];
NSLog(@"%d", [set containsObject:str]); // returns 1
[str appendString:@"BLA"];
NSLog(@"%d", [set containsObject:str]); // returns 0
NSLog(@"%d", [set.allObjects containsObject:str]); // returns 1
-
Lily Ballard almost 10 years@jowie:
NSSet
is a hash table.-[NSMutableString hash]
depends on the contents of the string. Mutating the string when it's in the set is explicitly unsupported (same as mutating it when it's in anNSDictionary
), because that changes the hash, which makes lookup fail. However,set.allObjects
produces anNSArray
which does not usehash
. -
jowie almost 10 yearsInteresting that it changes the hash. Why does it do that?
-
Lily Ballard almost 10 years@jowie: Because the alternative is for every single
NSMutableString
to have the same hash, which would produce absolutely abysmal performance when stored in dictionaries/sets. The simple rule is you're not supposed to mutate an object that's been placed into anNSSet
or used as the key for anNSDictionary
. -
jowie almost 10 yearsSo would it be a correct analogy to say that an
NSSet
is like a key-onlyNSDictionary
(in the same way that anNSArray
is a bit like a value-onlyNSDictionary
)? BecauseNSSet
items are unique, a bit likeNSDictionary
keys? -
Lily Ballard almost 10 years@jowie: An
NSSet
is effectively anNSDictionary
that has no value, that's correct. But no, anNSArray
is nothing like a value-onlyNSDictionary
(besides all the performance differences,NSDictionary
s are unsorted andNSArray
s are sorted).