NSSet versus NSArray

10544 ワード

最近、c++コードをobjective cに変更する必要があります.c++コードではstd::listコンテナに使用できます.検索するとNSSetとNSArrayはどちらも基準に合っていることがわかります.いったいどれを使いますか.
次はネットで検索した一般的な答えです.
NSSetと私たちがよく使うNSArryの違いは、1つの要素を検索するとき、NSSetはNSArrayよりも効率が高く、主にアルゴリズムhash(ハッシュ)を使用しています.開発文書では、You can use sets as an alternative to arrays when the order of elements isn’t important and performance in testing whether an obis contained in the set is a consideration-while arrays are ordered,testing for membership is slower than with sets.
例えば、要素Aを格納すると、hashアルゴリズムは直接Aが格納すべき位置を見つけることができます.同様に、Aにアクセスすると、hashプロシージャがAストレージの場所を見つけることができます.NSArrayでは、Aが配列中にないことを知りたければ、配列全体を便利にする必要があり、明らかに効率が低い.
でも私は愚かですね.1つの値を検索するとNSSetが一番速いということだけを理解していますが、他の状況はどうですか.だから実験をしました
//
//  main.m
//  test
//
//  Created by yanzhao on 13-12-9.
//  Copyright (c) 2013  yanzhao. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        NSInteger iterationIndex;
        NSAutoreleasePool *innerPool;
        const NSInteger NUM_ELEMENTS = 1000000;
        const NSInteger NUM_TEST_ITERATIONS = 3;
        NSDate *startTime;
        NSDate *endTime;
        NSMutableArray *objects = [NSMutableArray arrayWithCapacity:NUM_ELEMENTS];
        
        NSLog(@"Constructing test data for %d elements.", NUM_ELEMENTS);
        
        //
        // Preconstruct the arrays of objects to use in the tests
        //
        NSAutoreleasePool *constructionPool = [[NSAutoreleasePool alloc] init];
        for (iterationIndex = 0; iterationIndex < NUM_ELEMENTS; iterationIndex++)
        {
            NSNumber *objectValue = [NSNumber numberWithInteger:iterationIndex];
            [objects addObject:objectValue];
        }
        [constructionPool drain];
        
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++)
        {
            NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
            
            NSLog(@"=== Beginning test loop. Iteration %d of %d ===", i + 1, NUM_TEST_ITERATIONS);
            
            NSMutableArray *arrayOfObjects = [NSMutableArray arrayWithCapacity:NUM_ELEMENTS];
            NSMutableArray *unsizedArray = [NSMutableArray array];
            NSMutableSet *setOfObjects = [NSMutableSet setWithCapacity:NUM_ELEMENTS];
            NSMutableSet *setFromArray = nil;
            NSMutableSet *unsizedSet = [NSMutableSet set];
            
            //
            // Test 1: Array construction when arrayWithCapacity: is used
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in objects)
            {
                [arrayOfObjects addObject:number];
            }
            endTime = [NSDate date];
            NSLog(@"Constructing the preallocated array took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //
            // Test 2: Array construction when arrayWithCapacity: is NOT used
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in objects)
            {
                [unsizedArray addObject:number];
            }
            endTime = [NSDate date];
            NSLog(@"Constructing the unpreallocated array took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //
            // Test 2: Array construction when arrayWithCapacity: is NOT used
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in arrayOfObjects)
            {
            }
            endTime = [NSDate date];
            NSLog(@"Iterating the array took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //		//
            //		// Test 2a: Array querying by isEqualTo:
            //		//
            //		innerPool = [[NSAutoreleasePool alloc] init];
            //		startTime = [NSDate date];
            //		for (NSNumber *number in objects)
           // 		{
            //			[arrayOfObjects indexOfObject:number];
            //		}
            //		endTime = [NSDate date];
            //		NSLog(@"Array querying by isEqualTo: took %g seconds",
            //			[endTime timeIntervalSinceDate:startTime]);
            //		[innerPool drain];
            //
            //		//
            //		// Test 2b: Array querying by pointer value
            //		//
            //		innerPool = [[NSAutoreleasePool alloc] init];
            //		startTime = [NSDate date];
            //		for (NSNumber *number in objects)
            //		{
            //			[arrayOfObjects indexOfObjectIdenticalTo:number];
            //		}
            //		endTime = [NSDate date];
            //		NSLog(@"Array querying by pointer value took %g seconds",
            //			[endTime timeIntervalSinceDate:startTime]);
            //		[innerPool drain];
            
            //
            // Test 3: Set construction when setWithCapacity: is used
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in objects)
            {
                [setOfObjects addObject:number];
            }
            endTime = [NSDate date];
            NSLog(@"Constructing the preallocated set took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //
            // Test 4: Set construction when setWithCapacity: is NOT used
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in objects)
            {
                [unsizedSet addObject:number];
            }
            endTime = [NSDate date];
            NSLog(@"Constructing the unpreallocated set took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //
            // Test 4z: Set construction directly from an array of objects
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            setFromArray = [NSSet setWithArray:objects];
            endTime = [NSDate date];
            NSLog(@"Constructing the set from an array took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //
            // Test 4y: Set iterating
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in setOfObjects)
            {
            }
            endTime = [NSDate date];
            NSLog(@"Iterating the set took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            //
            // Test 4a: Set querying
            //
            innerPool = [[NSAutoreleasePool alloc] init];
            startTime = [NSDate date];
            for (NSNumber *number in objects)
            {
                [setOfObjects containsObject:number];
            }
            endTime = [NSDate date];
            NSLog(@"Set querying took %g seconds",
                  [endTime timeIntervalSinceDate:startTime]);
            [innerPool drain];
            
            [loopPool drain];
        }
        
        
    }
    return 0;
}
実行後の結果
2013-12-09 23:13:13.438 test[425:303] Constructing test data for 1000000 elements.
2013-12-09 23:13:13.511 test[425:303] === Beginning test loop. Iteration 1 of 3 ===
2013-12-09 23:13:13.547 test[425:303] Constructing the preallocated array took 0.029372 seconds
2013-12-09 23:13:13.604 test[425:303] Constructing the unpreallocated array took 0.055353 seconds
2013-12-09 23:13:13.610 test[425:303] Iterating the array took 0.00526196 seconds
2013-12-09 23:13:13.807 test[425:303] Constructing the preallocated set took 0.196128 seconds
2013-12-09 23:13:14.369 test[425:303] Constructing the unpreallocated set took 0.560845 seconds
2013-12-09 23:13:14.561 test[425:303] Constructing the set from an array took 0.189504 seconds
2013-12-09 23:13:14.594 test[425:303] Iterating the set took 0.013954 seconds
2013-12-09 23:13:14.761 test[425:303] Set querying took 0.166328 seconds
2013-12-09 23:13:14.822 test[425:303] === Beginning test loop. Iteration 2 of 3 ===
2013-12-09 23:13:14.872 test[425:303] Constructing the preallocated array took 0.044945 seconds
2013-12-09 23:13:14.920 test[425:303] Constructing the unpreallocated array took 0.043245 seconds
2013-12-09 23:13:14.926 test[425:303] Iterating the array took 0.00522602 seconds
2013-12-09 23:13:15.137 test[425:303] Constructing the preallocated set took 0.20949 seconds
2013-12-09 23:13:15.638 test[425:303] Constructing the unpreallocated set took 0.500495 seconds
2013-12-09 23:13:15.806 test[425:303] Constructing the set from an array took 0.166952 seconds
2013-12-09 23:13:15.842 test[425:303] Iterating the set took 0.013066 seconds
2013-12-09 23:13:16.000 test[425:303] Set querying took 0.15639 seconds
2013-12-09 23:13:16.053 test[425:303] === Beginning test loop. Iteration 3 of 3 ===
2013-12-09 23:13:16.091 test[425:303] Constructing the preallocated array took 0.032836 seconds
2013-12-09 23:13:16.137 test[425:303] Constructing the unpreallocated array took 0.044544 seconds
2013-12-09 23:13:16.143 test[425:303] Iterating the array took 0.00509703 seconds
2013-12-09 23:13:16.339 test[425:303] Constructing the preallocated set took 0.195937 seconds
2013-12-09 23:13:16.841 test[425:303] Constructing the unpreallocated set took 0.501613 seconds
2013-12-09 23:13:17.006 test[425:303] Constructing the set from an array took 0.164313 seconds
2013-12-09 23:13:17.043 test[425:303] Iterating the set took 0.012957 seconds
2013-12-09 23:13:17.200 test[425:303] Set querying took 0.156024 seconds
Program ended with exit code: 0

以上の結果から、
NSArrayを使います.検索機能が必要でも、データ量が少なく頻繁でない場合はNSSetは使用しないでください
本当にNSSetを使用する必要があり、データ・オブジェクトが一意であることを知っている場合は、NSArrayを構築してからsetWithArray:NSSetを構築することをお勧めします.