NSMutableArray vs NSArray which is better

2020-05-27 04:11发布

This is a bit of a silly question, but if I want to add an object to an array I can do it with both NSMutableArray and NSArray, which should I use?

NSMutableArray * array1;
[array1 addObject:obj];
NSArray * array2;
array2 = [array2 arrayByAddingObject:obj];

标签: objective-c
6条回答
Evening l夕情丶
2楼-- · 2020-05-27 04:59

Even the Q and the answer are very old, someone has to correct it.

  1. What does "better" mean? Better what? Your Q leaks of information what the problem is and it is highly opinion-based. However, it is not closed.

If you are talking about performance, you can measure it yourself. But remember Donald Knuth: "Premature optimization is the root of all evil".

  1. If I take your Q seriously, "better" can mean runtime performance, memory footprint, or architecture. For the first two topics it is easy to check yourself. So no answer is needed.

On an architectural point of view, things become more complicated.

First of all I have to mention, that having an instance of NSArray does not mean, that it is immutable. This is, because in Cocoa the mutable variants of collections are subclasses of the immutable variants. Therefore an instance of NSMutableArray is an instance of NSArray, but obviously mutable.

One can say that this was no good idea, especially when thinking about Barbara and Jeanette and there is a relation to the circle-ellipse problem, which is not easy to solve. However, it is as it is.

So only the docs can give you the information, whether a returned instance is immutable or not. Or you do a runtime check. For this reason, some people always do a -copy on every mutable collection.

However, mutability is another root of all evil. Therefore: If it is possible, always create an instance of NSArray as final result. Write that in your docs, if you return that instance from a method (esp. getter) or not, so everyone can rely on immutability or not. This prevents unexpected changes "behind the scene". This is important, not 0.000000000003 sec runtime or 130 bytes of memory.

查看更多
▲ chillily
3楼-- · 2020-05-27 05:05

This test gives the best answer:

Method 1:

NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
NSMutableArray *mutableItems = [[NSMutableArray alloc] initWithCapacity:1000];
for (int i = 0; i < 10000; i++) {
    [mutableItems addObject:[NSDate date]];
}
NSTimeInterval  end = [NSDate timeIntervalSinceReferenceDate];
NSLog(@"elapsed time = %g", (end - start) * 1000.0);

Method 2:

...
NSArray *items = [[[NSArray alloc] init] autorelease];
or (int i = 0; i < 10000; i++) {
    items = [items arrayByAddingObject:[NSDate date]];
}
...

Output:

Method 1: elapsed time = 0.011135 seconds.    
Method 2: elapsed time = 9.712520 seconds.
查看更多
Lonely孤独者°
4楼-- · 2020-05-27 05:10

NSMutableArray is not threadsafe, while NSArray is. This could be a huge problem if you're multithreading.
NSMutableArray and NSArray both are build on CFArray, performance/complexity should be same. The access time for a value in the array is guaranteed to be at worst O(lg N) for any implementation, current and future, but will often be O(1) (constant time). Linear search operations similarly have a worst case complexity of O(N*lg N), though typically the bounds will be tighter, and so on. Insertion or deletion operations will typically be linear in the number of values in the array, but may be O(N*lg N) clearly in the worst case in some implementations.

查看更多
爷的心禁止访问
5楼-- · 2020-05-27 05:14

An NSArray object manages an immutable array—that is, after you have created the array, you cannot add, remove, or replace objects. You can, however, modify individual elements themselves (if they support modification). The mutability of the collection does not affect the mutability of the objects inside the collection. You should use an immutable array if the array rarely changes, or changes wholesale.

An NSMutableArray object manages a mutable array, which allows the addition and deletion of entries, allocating memory as needed. For example, given an NSMutableArray object that contains just a single dog object, you can add another dog, or a cat, or any other object. You can also, as with an NSArray object, change the dog’s name—and in general, anything that you can do with an NSArray object you can do with an NSMutableArray object. You should use a mutable array if the array changes incrementally or is very large—as large collections take more time to initialize.

查看更多
Fickle 薄情
6楼-- · 2020-05-27 05:16

When deciding which is best to use:

NSMutableArray is primarily used for when you are building collections and you want to modify them. Think of it as dynamic.

NSArray is used for read only inform and either:

  • used to populate an NSMutableArray, to perform modifications
  • used to temporarily store data that is not meant to be edited

What you are actually doing here:

NSArray * array2;
array2 = [array2 arrayByAddingObject:obj];

is you are creating a new NSArray and changing the pointer to the location of the new array you created.

You are leaking memory this way, because it is not cleaning up the old Array before you add a new object.

if you still want to do this you will need to clean up like the following:

NSArray *oldArray;
NSArray *newArray;
newArray = [oldArray arrayByAddingObject:obj];
[oldArray release];

But the best practice is to do the following:

NSMutableArray *mutableArray;
// Initialisation etc
[mutableArray addObject:obj];
查看更多
Summer. ? 凉城
7楼-- · 2020-05-27 05:17

Use NSMutableArray, that is what it is there for. If I was looking at code and I saw NSArray I would expect it's collection to stay constant forever, whereas if I see NSMuteableArray I know that the collection is destined to change.

It might not sound like much right now, but as your project grows and as you spend more time on it you will see the value of this eventually.

查看更多
登录 后发表回答