NSMutableArray vs NSArray哪个更好

时间:2021-08-07 16:11:33

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和NSArray来做,我应该使用它?

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

6 个解决方案

#1


8  

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.

使用NSMutableArray,就是它的用途。如果我正在查看代码,我看到NSArray,我希望它的集合永远保持不变,而如果我看到NSMuteableArray,我知道该集合注定要改变。

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.

现在听起来可能不是很多,但随着你的项目的发展和你花费更多的时间,你最终会看到它的价值。

#2


9  

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.

NSMutableArray不是线程安全的,而NSArray是。如果你是多线程的话,这可能是个大问题。 NSMutableArray和NSArray都是基于CFArray构建的,性能/复杂性应该相同。对于任何实现,当前和未来,阵列中值的访问时间保证最差为O(lg N),但通常为O(1)(恒定时间)。类似地,线性搜索操作具有O(N * lg N)的最差情况复杂度,但是通常边界将更紧密,等等。插入或删除操作通常在阵列中的值的数量上是线性的,但在一些实现中在最坏的情况下可以清楚地为O(N * lg N)。

#3


8  

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.

NSMutableArray主要用于构建集合并且您想要修改它们。把它想象成动态的。

NSArray is used for read only inform and either:

NSArray用于只读通知,并且:

  • used to populate an NSMutableArray, to perform modifications
  • 用于填充NSMutableArray,以执行修改

  • 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.

你是在创建一个新的NSArray并将指针更改为你创建的新数组的位置。

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];

#4


1  

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

即使Q和答案都很老,有人必须纠正它。

  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.
  2. “更好”是什么意思?哪个更好?你的Q泄漏信息是什么问题,它是高度意见的。但是,它没有关闭。

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

如果您在谈论性能,可以自己测量。但请记住Donald Knuth:“过早优化是所有邪恶的根源”。

  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.
  2. 如果我认真对待你的Q,“更好”可能意味着运行时性能,内存占用或架构。对于前两个主题,很容易检查自己。所以不需要回答。

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.

首先,我必须提一下,拥有一个NSArray实例并不意味着它是不可变的。这是因为在Cocoa中,集合的可变变体是不可变变体的子类。因此,NSMutableArray的一个实例是NSArray的一个实例,但显然是可变的。

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.

因此,只有文档可以为您提供信息,返回的实例是否是不可变的。或者您进行运行时检查。出于这个原因,有些人总是对每个可变集合进行-copy。

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.

然而,可变性是所有邪恶的另一个根源。因此:如果可能,请始终创建NSArray的实例作为最终结果。如果你从一个方法(特别是getter)返回那个实例,那么在你的文档中写下这个,所以每个人都可以依赖不变性。这可以防止“幕后”的意外更改。这很重要,不是0.000000000003秒运行时或130字节内存。

#5


1  

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.

NSArray对象管理不可变数组 - 也就是说,在创建数组后,您无法添加,删除或替换对象。但是,您可以自行修改单个元素(如果它们支持修改)。集合的可变性不会影响集合中对象的可变性。如果数组很少更改,则应使用不可变数组,或者更改批发。

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.

NSMutableArray对象管理可变数组,允许添加和删除条目,根据需要分配内存。例如,给定一个只包含一个狗对象的NSMutableArray对象,您可以添加另一只狗,猫或任何其他对象。与NSArray对象一样,您也可以更改狗的名称 - 通常,您可以使用NSMutableArray对象对NSArray对象执行任何操作。如果数组以递增方式更改或非常大,则应使用可变数组 - 因为大型集合需要更多时间进行初始化。

#6


-1  

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.

#1


8  

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.

使用NSMutableArray,就是它的用途。如果我正在查看代码,我看到NSArray,我希望它的集合永远保持不变,而如果我看到NSMuteableArray,我知道该集合注定要改变。

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.

现在听起来可能不是很多,但随着你的项目的发展和你花费更多的时间,你最终会看到它的价值。

#2


9  

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.

NSMutableArray不是线程安全的,而NSArray是。如果你是多线程的话,这可能是个大问题。 NSMutableArray和NSArray都是基于CFArray构建的,性能/复杂性应该相同。对于任何实现,当前和未来,阵列中值的访问时间保证最差为O(lg N),但通常为O(1)(恒定时间)。类似地,线性搜索操作具有O(N * lg N)的最差情况复杂度,但是通常边界将更紧密,等等。插入或删除操作通常在阵列中的值的数量上是线性的,但在一些实现中在最坏的情况下可以清楚地为O(N * lg N)。

#3


8  

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.

NSMutableArray主要用于构建集合并且您想要修改它们。把它想象成动态的。

NSArray is used for read only inform and either:

NSArray用于只读通知,并且:

  • used to populate an NSMutableArray, to perform modifications
  • 用于填充NSMutableArray,以执行修改

  • 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.

你是在创建一个新的NSArray并将指针更改为你创建的新数组的位置。

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];

#4


1  

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

即使Q和答案都很老,有人必须纠正它。

  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.
  2. “更好”是什么意思?哪个更好?你的Q泄漏信息是什么问题,它是高度意见的。但是,它没有关闭。

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

如果您在谈论性能,可以自己测量。但请记住Donald Knuth:“过早优化是所有邪恶的根源”。

  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.
  2. 如果我认真对待你的Q,“更好”可能意味着运行时性能,内存占用或架构。对于前两个主题,很容易检查自己。所以不需要回答。

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.

首先,我必须提一下,拥有一个NSArray实例并不意味着它是不可变的。这是因为在Cocoa中,集合的可变变体是不可变变体的子类。因此,NSMutableArray的一个实例是NSArray的一个实例,但显然是可变的。

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.

因此,只有文档可以为您提供信息,返回的实例是否是不可变的。或者您进行运行时检查。出于这个原因,有些人总是对每个可变集合进行-copy。

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.

然而,可变性是所有邪恶的另一个根源。因此:如果可能,请始终创建NSArray的实例作为最终结果。如果你从一个方法(特别是getter)返回那个实例,那么在你的文档中写下这个,所以每个人都可以依赖不变性。这可以防止“幕后”的意外更改。这很重要,不是0.000000000003秒运行时或130字节内存。

#5


1  

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.

NSArray对象管理不可变数组 - 也就是说,在创建数组后,您无法添加,删除或替换对象。但是,您可以自行修改单个元素(如果它们支持修改)。集合的可变性不会影响集合中对象的可变性。如果数组很少更改,则应使用不可变数组,或者更改批发。

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.

NSMutableArray对象管理可变数组,允许添加和删除条目,根据需要分配内存。例如,给定一个只包含一个狗对象的NSMutableArray对象,您可以添加另一只狗,猫或任何其他对象。与NSArray对象一样,您也可以更改狗的名称 - 通常,您可以使用NSMutableArray对象对NSArray对象执行任何操作。如果数组以递增方式更改或非常大,则应使用可变数组 - 因为大型集合需要更多时间进行初始化。

#6


-1  

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.