NSArray 大小和可变性

Posted

技术标签:

【中文标题】NSArray 大小和可变性【英文标题】:NSArray size and mutability 【发布时间】:2011-11-24 05:03:06 【问题描述】:

在 Java 中,我通常初始化特定大小的数组,然后随着代码的继续添加和替换对象。在 Objective C 中,我不能用 NSArray 做到这一点。我从 Java 移植过来的代码通常必须使用 NSMutableArray,我认为它的效率低于 NSArray。 (关于 NSMutableArray 如何存储它的成员,我最好的猜测是使用链表,但我可能是错的)

Objective C 中是否有任何类型的数组具有固定大小并允许在数组内进行更改?为什么不能用 NSArray 替换某个对象上的对象?我可以用 C 数组做到这一点,为什么不是 Objective C?

【问题讨论】:

Objective-C 只是 C 的超集。如果您愿意,可以使用 C 数组。不过,你为什么认为它更慢?你是如何测试它的? 我也不会解雇 NSMutableArray。它被广泛使用,除非您可以衡量性能问题,否则您可能会选择使用它。 CFMutableArray(从 NSMutableArray 免费桥接)保证 O(log N) 访问时间。这不能是链表。 从 Java 迁移到 Cocoa 时,无论在概念上还是在代码中,都用 NSMutableArray 替换您的列表。 Java Array 的等价物是 C 数组,当然,Java 本身就是从这个数组中来的。 【参考方案1】:

你的假设是错误的,NSMutableArray 不会比普通的NSArray 慢。

NSMutableArray 不会使用链表,它将使用dynamic array。除了需要调整大小的插入之外,它与普通数组一样快。但是由于它们之间的距离呈指数级增长,因此如果您不调整大小,它的摊销几乎相同,并且相同。

它与Java的ArrayList基本相同。

【讨论】:

谢谢!但是当我插入一个对象并且相邻的内存已经分配时会发生什么? 如果相邻的内存已经分配,​​下一个更大的数组将被分配到别处,并且值将被复制过来。这是最坏的情况,但摊销 O(1) 的证明假设了这种最坏情况的行为。一次调用会更慢,但随着数组变大,这种情况很少发生(每 n 次调用只有一次 O(n) 调用使其成为 O(1))。【参考方案2】:

在 Objective-C 中,许多类都有可变和不可变的变体。不可变的 NSArray 可能会带来性能或内存方面的好处,但如果您需要一个可以修改的数组,只需使用 NSMutableArray。没有理由惊慌或担心。这就是他们的目的。

您可以初始化具有预期容量的可变数组,尽管您不会永远受限于该容量 - 如果需要,数组将超出容量。

int numberOfItems = ...
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:numberOfItems];

NSArray 可用的任何优化优势都取决于它是不可变的这一事实。所以抛开语法不谈,当您实际需要使用的是可变对象时(例如,您需要替换您的情况下的对象),您无法意识到不可变对象的好处。

【讨论】:

【参考方案3】:

不要认为NSMutableArray 对你来说太慢了。简介,不要猜测。

如果您正在开发 Mac OS X 应用程序,还可以查看 NSPointerArray。它在 ios 上不可用。

【讨论】:

【参考方案4】:

如果你想替换某个对象,你必须使用NSMutableArray。并使用

创建数组
 + (id)arrayWithCapacity:(NSUInteger)numItems   

- (id)initWithCapacity:(NSUInteger)numItems

NSMutableArray 并指定数组的大小。

【讨论】:

以上是关于NSArray 大小和可变性的主要内容,如果未能解决你的问题,请参考以下文章

IOS 中runtime 不可变数组__NSArray0 和__NSArrayI

text 获取NSArray和NSDictionary的深度可变副本

Objective - C NSArray不可变数组和NSMutableArray可变数组

OC-NSArray

NSDictionary  NSSet和NSArray的区别

类型为 var Array 的 Swift 类字段被转换为不可变的 NSArray 而不是 NSMutableArray