Подтвердить что ты не робот

Различия между [NSArray arrayWithArray:] и [NSArray copy]

В последнее время я много работаю с массивами, и мне интересно.. какие различия между этими двумя строками.

NSArray *array = [NSArray arrayWithArray:someArray];

и

NSArray *array = [someArray copy];

Какая из них быстрее? Что в случае NSMutableArray и mutableCopy?

4b9b3361

Ответ 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)