When I use NSMutableArray or NSMutableDictionary, if I know the number of elements I want to put in or the max number of elements, I usually create them with arrayWithCapacity or dictionaryWithCapacity, but I wonder does it really help to specify an (initial) capacity for the array/dictionary?
I don’t know how it is implemented internally, but I believe it is possible that when the number of elements in a collection hits the capacity or even approaches the capacity, the collection may extend its capacity, so if I created a mutable array with capacity 32, as long as I put the 32nd object in it, it will expand itself to another capacity? Or even if I put the 30st object in it, its capacity will be expanded as it thinks there will be more objects?
So if these methods really help, should I use something like:
*withCapacity:maxNumberOfElements * 1.5
instead of
*withCapacity:maxNumberOfElements
so it will have more than enough capacity for my objects and won’t expand when I put in all the objects?
This is useful when you are planning to populate a collection with a large number of elements, or when you know the exact number of elements that you are going to load. Resizing a collection takes CPU cycles, so resizing unnecessarily ultimately translates into reducing the time your device can operate on a battery.
Consider this example: let’s say you are about to load 3000 elements into an array. If you allocate the default array with space for, say, 16 items, the array will need to resize eight times before arriving at the size necessary to hold 3000 elements. The elements copied in the initial positions will need to be copied each time the array is resized, resulting in 3000+ additional copy operations. When you know the exact number of elements, you can prevent the copying from happening.
In addition, your array will not waste memory for elements that you are not going to add: if you add 3000 elements one by one, the array may grow to 4000 internally in anticipation of more elements; the last 1000 elements will be wasted.
To summarize, you should initialize your collections with capacity when you know the exact target size for sure. This situation comes up often when you deserialize data from a file or a network connection. In situations when you do not know the size, it is better not to make guesses, and let the default initialization run its course.