Различия между [NSArray arrayWithArray:] и [NSArray copy]
В последнее время я много работаю с массивами, и мне интересно.. какие различия между этими двумя строками.
NSArray *array = [NSArray arrayWithArray:someArray];
и
NSArray *array = [someArray copy];
Какая из них быстрее? Что в случае NSMutableArray
и mutableCopy
?
Ответы
Ответ 1
Какая из них быстрее?
Не беспокойтесь об этом. Преждевременная оптимизация.
Основное отличие: первый подход приводит к автореализованной "копии", которой вы не владеете, и ее не нужно выпускать, тогда как вы владеете объектом, созданным во второй строке.
Между тем оба массива будут неизменными.
Ответ 2
В дополнение к другим ответам также обратите внимание, что, когда someArray
равно нулю,
первая строка сделает array
указывать на пустой массив, а второй сделает
он указывает на ноль. Это может быть важным отличием, особенно в изменяемых массивах.
Ответ 3
Разница между ними состоит в том, что последняя будет сохранена. Первый будет автореализован.
Обе версии делают мелкую копию массива.
NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];
Должна дать вам предупреждение о компиляторе, поскольку вы будете пытаться назначить NSArray
для NSMutableArray
.
Использовать.
NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];
Что быстрее? Не беспокойтесь, они все намного быстрее, чем остальные вещи, которые вы будете делать. Обратитесь к инструментам, если вы действительно заботитесь.
Ответ 4
Основное отличие состоит в том, что -copy
лучше знает, как копировать себя (может сделать это более эффективно и, возможно, использовать более адаптированный подкласс NSArray), а +arrayWithArray:
создаст новый экземпляр NSArray
(ну, в факт конкретного класса, используемого Foundation для массивов) и передать его тем же списком объектов из исходного объекта. Также он добавит дополнительную авторекламу.
Итак, -copy
(очень), вероятно, более эффективен.
Фактически для неизменяемого NSArrays
-copy
просто выполняет -retain
, поэтому даже не создает новый экземпляр.
Ответ 5
NSMutableArray *arr = [NSMutableArray array];
for ( int i = 0; i < 10000; i ++)
{
[arr addObject:@(i*1000000ULL)];
}
// MARK
// arr = (id)[NSArray arrayWithArray:arr];
NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate];
NSArray *res = nil;
for ( int i = 0; i < 10000; i ++)
{
res = [arr copy];
}
NSLog(@"time A: %f", [NSDate timeIntervalSinceReferenceDate] - t);
t = [NSDate timeIntervalSinceReferenceDate];
for ( int i = 0; i < 10000; i ++)
{
res = [NSArray arrayWithArray:arr];
}
NSLog(@"time B: %f", [NSDate timeIntervalSinceReferenceDate] - t);
время A: 1.572795, время B: 1.539150, B [NSArray arrayWithArray:] всегда быстрее, но разница во времени очень мала. Но если мы раскомментируем "MARK" и получим копию из NSArray вместо NSMutableArray, у нас будет другая среда выполнения A: 0.000473 время B: 1.548400 результат: ~ 3200x раз быстрее
Ответ 6
Один из них, вероятно, быстрее. Запустите их миллион раз и посмотрите, выиграет ли кто-нибудь.
В случае NSArray
vs NSMutableArray
неизменяемый массив, который копируется, не должен фактически возвращать копию, так как он не может измениться. Однако, если у вас есть изменяемый массив, его нужно будет скопировать, так как вы можете изменить оригинал. И, конечно, для выполнения изменяемой копии всегда нужно возвращать новый объект.
Во всем приложении скорость и разность памяти, вероятно, не будут иметь значения по сравнению со всем остальным, что происходит.
Ответ 7
В Swift это совсем другое. Благодаря новому open-source Foundation для Swift мы знаем, что в то время как init(array:)
создает новый массив с указанными элементами (если они есть), copy()
просто возвращает self
.
public override func copy() -> AnyObject {
return copyWithZone(nil)
}
public func copyWithZone(zone: NSZone) -> AnyObject {
return self
}
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSArray.swift#L82
public convenience init(array: [AnyObject]) {
self.init(array: array, copyItems: false)
}
public convenience init(array: [AnyObject], copyItems: Bool) {
let optionalArray : [AnyObject?] =
copyItems ?
array.map { return Optional<AnyObject>(($0 as! NSObject).copy()) } :
array.map { return Optional<AnyObject>($0) }
// This would have been nice, but "initializer delegation cannot be nested in another expression"
// optionalArray.withUnsafeBufferPointer { ptr in
// self.init(objects: ptr.baseAddress, count: array.count)
// }
let cnt = array.count
let buffer = UnsafeMutablePointer<AnyObject?>.alloc(cnt)
buffer.initializeFrom(optionalArray)
self.init(objects: buffer, count: cnt)
buffer.destroy(cnt)
buffer.dealloc(cnt)
}
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSArray.swift#L116
Итак, очевидно, copy()
быстрее, и теперь вы знаете, как они работают! (Только в Swift)