views:

903

answers:

3

These two collection types are rarely used by me as I'm typically using their counter parts, NSArray, NSDictionary and the equivalent mutables. I have a feeling I'm missing out on a collection which can act much faster than the other two in certain situations. When is the ideal time to use these and how?

+10  A: 

NSSet is used when you frequently wish to test for membership of an object, but don't care about the ordering and don't need the collection to contain duplicate objects. An NSSet doesn't store its objects in any particular order; rather, the class is expressly designed to efficiently test whether an object exists in the collection.

The same goes for NSCountedSet, although NSCountedSet also keeps a count of duplicated objects.

So in a nutshell: use a set when you are concerned about testing for membership, rather than just keeping a collection of objects (some of which may be duplicated, as decided by an isEqualTo method of some sort).

mipadi
+5  A: 

Following up on midpadi, Many uses of NSArray should be replaced with NSSet. NSSet is a collection of unique objects. NSArray is a collection of ordered objects. If your objects do not have an inherent order and are unique, you should use NSSet.

I very often keep an NSSet in the model layer, and let the UI components who require an order create their own NSArrays. For instance, consider the case of a "buddy list" made up of "buddies." The buddy list is itself unordered; it's just a collection. And the objects need to be unique. At the UI layer, however, you want an order, and you might even want to put the same buddy in multiple groups (Favorite and Offline for instance). But these are UI issues, and the model layer shouldn't need to worry about them.

NSSet *buddies = [buddyList allBuddies];
BOOL isBuddy = [buddyList containsObject:buddy];

NSArray *buddyList = [[buddyList allBuddies] sortedAraryUsingSelector:[self buddySortSelector]];

When a new buddy shows up, BuddyList will post a notification (BuddyListDidAddBuddiesNotification), that includes an NSSet of added buddies in its userInfo. So UI elements who are observing this can insert the buddies into their lists in whatever sort order is appropriate. This makes list animations very easy, which is much harder if you maintain all your sorted versions at the model layer.

When you have two NSSets, it's pretty easy to figure out the differences between them and construct a series of deletes and adds to turn one into the other (again, useful for animations). It's much more complicated to do this with NSArray.

So my recommendation is to default to NSSet. You should only use NSArray when you actually need ordering. This is unfortunately backwards of how most people do it.

Rob Napier
Core Data essentially works with NSSets
Abizern
+1  A: 

In addition to the other answers, which talk mainly of Sets but not so much of Counted Sets, you might be wondering when is best to use a counted set. A counted set is useful for things like weighting or other statistical algorithms: at the end you can ultimately create an ordered array of its contents sorted using the stored count.

Another option would be in uniquing tables, or in a form of reference counter/garbage collector. Using a counted set would enable tests for inclusion (i.e. returning an existing identical object rather than creating a new one—similar to what CoreData does internally) whilst also performing a sort of reference counting on the values it includes, since the object would only be released by the set once its count reaches 0.

Jim Dovey