NSMutableArray和NSArray哪个更好?

12

这可能是一个有点傻的问题,但是如果我想将一个对象添加到数组中,我可以使用 NSMutableArrayNSArray,我该使用哪个?

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

1
在这两种情况下,你的数组都将是nil,因为对象从未被初始化。你需要像这样写:NSMutableArray *array1 = [NSMutableArray array]; - pkamb
6个回答

10

使用NSMutableArray,这就是它存在的原因。如果我看到代码中使用了NSArray,我会认为它的集合将永远保持不变,而如果我看到NSMuteableArray,我知道该集合注定会发生变化。

现在可能听起来不是很重要,但随着您的项目规模增长以及您花费更多时间在其上,您最终会意识到其价值。


由于NSMutableArrayNSArray的子类,因此您不能做出这样的假设。这是Cocoa中的设计缺陷,但它就是这样。确保不可变性的唯一方法是进行复制。(也许这是在数花生...) - Amin Negm-Awad

9

NSMutableArray 是不线程安全的,而 NSArray 是线程安全的。如果你在多线程环境下使用,这可能会是一个巨大的问题。
NSMutableArrayNSArray 都基于 CFArray 构建,性能/复杂度应该是相同的。对于数组中的值的访问时间保证最坏情况下为 O(lg N),对于任何实现,当前和未来,但通常为 O(1)(常数时间)。类似地,线性搜索操作的最坏复杂度也为 O(N*lg N),尽管通常边界会更紧,等等。插入或删除操作通常是与数组中的值的数量成线性关系的,但在某些实现中最坏情况下可能是 O(N*lg N)。


你在哪里读到了关于Objective-C数据结构性能的信息? - George

9

在决定使用哪个时:

NSMutableArray 主要用于构建集合并且希望修改它们。可以将其视为动态的。

NSArray 用于只读信息,要么:

  • 用于填充NSMutableArray以执行修改
  • 用于暂时存储不打算编辑的数据

实际上你在这里所做的是:

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

如果您正在创建一个新的NSArray并将指针更改为您创建的新数组的位置,则会出现内存泄漏。

这种方式会导致内存泄漏,因为它在添加新对象之前没有清理旧的Array。

如果您仍然想要这样做,您需要像以下这样清理:

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

但最佳实践是按照以下步骤进行:

NSMutableArray *mutableArray;
// Initialisation etc
[mutableArray addObject:obj];

2
一个NSArray对象管理一个不可变的数组,也就是说,在创建数组之后,您不能添加、删除或替换对象。但是,您可以修改单个元素本身(如果它们支持修改)。集合的可变性不会影响集合内部对象的可变性。如果数组很少更改或整体更改,应使用不可变数组。
一个NSMutableArray对象管理一个可变数组,允许添加和删除条目,并根据需要分配内存。例如,给定一个仅包含单个狗对象的NSMutableArray对象,您可以添加另一个狗、猫或任何其他对象。与NSArray对象一样,您也可以更改狗的名称,通常情况下,您可以对NSArray对象执行的任何操作都可以对NSMutableArray对象执行。如果数组逐步更改或非常大,则应使用可变数组,因为大型集合需要更多时间进行初始化。

2
即使问题和答案都很老,仍有人需要进行更正。
1. “更好”是什么意思?更好的什么?你的问题泄露了问题所在并且高度基于个人观点。然而,它没有被关闭。
2. 如果你认真考虑你的问题,“更好”可以指运行时性能、内存占用或架构。对于前两个主题,你可以自己检查。因此不需要回答。
从架构角度来看,事情变得更加复杂。
首先,我必须提到的是,拥有一个NSArray实例并不意味着它是不可变的。这是因为在Cocoa中,可变集合的子类是不可变集合的子类。因此,NSMutableArray的实例是一个NSArray的实例,但显然是可变的。

可以说这不是一个好主意,特别是当考虑到Barbara和Jeanette以及与圆-椭圆问题有关系时,这个问题并不容易解决。然而,事实就是如此。

因此,只有文档可以给您提供信息,返回的实例是否是不可变的。或者进行运行时检查。因此,一些人总是在每个可变集合上执行-copy

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


-1

这个测试提供最佳答案:

方法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);

方法二:

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

输出:

Method 1: elapsed time = 0.011135 seconds.    
Method 2: elapsed time = 9.712520 seconds.

哪个问题的最佳答案? - Amin Negm-Awad
在标题中提到Q:「NSMutableArray和NSArray哪个更好?」 - Igor
最佳是关于什么话题?内存占用?运行时性能?架构?最快等于最好是错误的,而且在大多数当今的应用程序中,性能是无意义的。通常不可变性是“最佳”的,因为可变性很难处理。 - Amin Negm-Awad
如果对你来说,“性能无关紧要”和“可变性难以处理” - 我没有任何评论。 - Igor
当然。你没有软件开发经验。 - Amin Negm-Awad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接