最近、私は配列に関して多くの作業をしています。[NSArray arrayWithArray:]と[NSArray copy]の相違点
NSArray *array = [NSArray arrayWithArray:someArray];
と
NSArray *array = [someArray copy];
それが高速であるのはどれですか? NSMutableArray
とmutableCopy
の場合はどうなりますか?
最近、私は配列に関して多くの作業をしています。[NSArray arrayWithArray:]と[NSArray copy]の相違点
NSArray *array = [NSArray arrayWithArray:someArray];
と
NSArray *array = [someArray copy];
それが高速であるのはどれですか? NSMutableArray
とmutableCopy
の場合はどうなりますか?
どちらが速いのですか?
心配しないでください。時期尚早の最適化。
主な違い:最初のアプローチでは、2番目の行に作成されたオブジェクトを所有している間に、所有していないautoreleased "コピー"がリリースされる必要はありません。 両方の配列は、そのままでは不変です。
おそらくそのうちの1つが高速です。百万回それらを実行し、誰かが勝つかどうかを確認します。
NSArray
とNSMutableArray
の場合、変更可能なので、コピーされる不変の配列は実際にコピーを返す必要はありません。ただし、配列を変更できる場合は、元の配列を変更できるのでコピーする必要があります。もちろん、可変コピーを実行すると常に新しいオブジェクトを返す必要があります。
あなたのアプリケーション全体では、スピードとメモリの違いは、おそらくそれが起こっているすべてのものと比較して問題にはならないでしょう。
2つの違いは、後者が保持されることです。前者はオートリリースされます。
どちらのバージョンでも、アレイのシャローコピーが作成されます。あなたはNSMutableArray
にNSArray
を代入しようとするよう
NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];
はあなたのコンパイラの警告を与える必要があります。
使用。
NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];
どちらが速いのですか?心配しないでください、彼らはあなたがやっているものの残りの部分よりもはるかに高速です。あなたが本当に気にしているのであれば、インストゥルメンツにチェック
主な違いは、(まあ、実際には具体的なクラスを使用-copy
が+arrayWithArray:
がNSArray
の新しいインスタンスを作成します。一方、(より効率的にそれを行うと、多分にNSArrayのより多くの適応サブクラスを使用することができます)自分自身をコピーする方法を良く知っているということですFoundationのby配列)、初期オブジェクトからのオブジェクトの同じリストを与えてください。また、それは余分なオートリリースを追加します。
だから-copy
は非常に効率的です。
実際には不変のNSArrays
の場合、-copy
は-retain
を実行しているだけなので、新しいインスタンスを作成する必要はありません。他の回答に加えて
これは正確ではありません。コピーを作成すると、新しい配列が作成されます。 – thierryb
簡単なテストツールで試してみることができます(ここで私が正しいと信じる他の非常に良い理由はありません) – Julien
@JulienあなたはFoundationクラスに精通しているようですが、NSArray 、NSDictionaryなどは変更可能ですか?すでに他の場所で議論が行われていますが、良い答えは見つかりませんでしたか? (-isKindOfClass:信頼できないと言われています。-respondsToSelector:@selector(addObject :)?)正しい方法を探しています...ありがとう! –
もsomeArray
がnil、 である場合、最初の行は、空の配列にarray
ポイントを作るし、第二は、nilに それポイントを作ることに注意します。これは、特に可変配列の重要な違いです。
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結果:スウィフトで〜3200倍高速
を、それは非常に異なるのです。 Swiftの新しいオープンソース基金のおかげで、init(array:)
は与えられたアイテム(もしあれば)を使って新しい配列を作成しますが、は単に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()
が速くなり、そして今、あなたは彼らの両方がどのように動作するかを知っています! (スイフトのみ)
スウィフトでのこのような仕組みが分かりました:) –
ARCはどうですか? –
私はARCで2番目のものを使うと言うので、オートリリースされていないので、オートリリースプールがフラッシュされるまで保持されません。しかし、同じrunloop内(または@ autoreleasepool内)にたくさんの配列を作成しない限り、それは早すぎる最適化です。 –