oc/object-c/ios哪种遍历NSArray/NSDictionary方式快?测试报告

做app的时候,总免不了要多次遍历数组或者字典。
究竟哪种遍历方式比较快呢?我做了如下测试:
首先定义测试用宏:

?


1

2

3

4

5

6

7

8

9

#define
MULogTimeintervalBegin(INFO) NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];\

NSTimeInterval

duration = 0;\

NSLog(@"MULogTimeintervalBegin:%@",
INFO)

#define
MULogTimeintervalPauseAndLog(INFO) duration = [NSDate timeIntervalSinceReferenceDate] - start;\

start
+= duration;\

NSLog(@"%@:%f",
INFO, duration);\

duration
= 0

#define
TESTSCALE 100000

接着编写测试代码:
NSarray:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

-
(
void)testArray

{

    NSMutableArray*
testArray = [
NSMutableArray

arrayWithCapacity:TESTSCALE];

    for

(
NSInteger

i = 1; i <= TESTSCALE; ++i) {

        [testArray
addObject:[
NSString

stringWithFormat:@
"%ld",
i]];

    }

    NSLog(@"init:%ld",
[testArray count]);

    

    __block
NSMutableString*
sum = [
NSMutableString

stringWithCapacity:TESTSCALE];

    

    MULogTimeintervalBegin(@"ArrayTest");

    NSUInteger

count = [testArray count];

    for

(
NSInteger

i = 0; i < count; ++i) {

        [sum
appendString:[testArray objectAtIndex:i]];

    }

    [sum
setString:@
""];

    MULogTimeintervalPauseAndLog(@"for
statement"
);

    

    for(NSString*
item in testArray) {

        [sum
appendString:item];

    }

    [sum
setString:@
""];

    MULogTimeintervalPauseAndLog(@"for-in");

    

    [testArray
enumerateObjectsUsingBlock:^(
id

obj,
NSUInteger

idx,
BOOL

*stop) {

        [sum
appendString:obj];

    }];

    [sum
setString:@
""];

    MULogTimeintervalPauseAndLog(@"enumerateBlock");

}

NSDictionary:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

-
(
void)testDictionary
{

    NSMutableDictionary*
testDic = [
NSMutableDictionary

dictionaryWithCapacity:TESTSCALE];

    for

(
NSInteger

i = 1; i <= TESTSCALE; ++i) {

        [testDic
setObject:@
"test"

forKey:[
NSString

stringWithFormat:@
"%ld",
i]];

    }

    NSLog(@"init:%ld",
[testDic count]);

    

    __block
NSMutableString*
sum = [
NSMutableString

stringWithCapacity:TESTSCALE];

    

    MULogTimeintervalBegin(@"DictionaryTest");

    for

(
NSString*
object in [testDic allValues]) {

        [sum
appendString:object];

    }

    [sum
setString:@
""];

    MULogTimeintervalPauseAndLog(@"for
statement allValues"
);

    

    for

(
id

akey in [testDic allKeys]) {

        [sum
appendString:[testDic objectForKey:akey]];

    }

    [sum
setString:@
""];

    MULogTimeintervalPauseAndLog(@"for
statement allKeys"
);

    

    [testDic
enumerateKeysAndObjectsUsingBlock:^(
id

key,
id

obj,
BOOL

*stop) {

        [sum
appendString:obj];

    }
];

    MULogTimeintervalPauseAndLog(@"enumeration");

}

下面是测试结果:
Test Case ‘-[LoopTestTests testArray]‘ started.
2012-08-02 17:14:22.061 otest[388:303] init:100000
2012-08-02 17:14:22.062 otest[388:303] MULogTimeintervalBegin:ArrayTest
2012-08-02 17:14:22.075 otest[388:303]for statement:0.013108
2012-08-02 17:14:22.083 otest[388:303]for-in:0.008186
2012-08-02 17:14:22.095 otest[388:303] enumerateBlock:0.012290
Test Case ‘-[LoopTestTests testArray]‘ passed (0.165 seconds).
Test Case ‘-[LoopTestTests testDictionary]‘ started.
2012-08-02 17:14:22.273 otest[388:303] init:100000
2012-08-02 17:14:22.274 otest[388:303] MULogTimeintervalBegin:DictionaryTest
2012-08-02 17:14:22.284 otest[388:303] for statement allValues:0.010566
2012-08-02 17:14:22.307 otest[388:303] for statement allKeys:0.022377
2012-08-02 17:14:22.330 otest[388:303] enumeration:0.023914
Test Case ‘-[LoopTestTests testDictionary]‘ passed (0.217 seconds).

可以看出对于数组来说,for-in方式遍历速度是最快的,普通风格的for和block方式速度差不多。对于字典来说,allValues方式遍历最快,allKeys和block差不多。
那么,为什么会这样呢?
NSArray:

?


1

2

3

for

(
NSInteger

i = 0; i < count; ++i) {

        [sum
appendString:[testArray objectAtIndex:i]];

}

这里由于存在:[objectAtIndex:i]这样的取操作,所以速度会有所下降。

?


1

2

3

for(NSString*
item in testArray) {

        [sum
appendString:item];

}

尽管也有取操作,但是绕开了oc的message机制,速度会快一点。也有可能是编译器为了for-in作了优化。
block为什么会慢一些这个有待研究。
NSDictionary:

?


1

2

3

for

(
id

akey in [testDic allKeys]) {

        [sum
appendString:[testDic objectForKey:akey]];

}

这个就很明显了,第二种方法多了一次objectForKey的操作。block的话有待研究。


google了一下,stackoverflow上面有类似的讨论:点击打开链接
大意是:for-in语法会对容器里面的元素的内存地址建立一个缓冲,遍历的时候从缓冲直接取得元素的地址而不是通过调用方法来获取,所以效率比较高。另外,这也是不能在循环体中修改容器元素的原因之一。

oc/object-c/ios哪种遍历NSArray/NSDictionary方式快?测试报告,布布扣,bubuko.com

时间: 2024-10-22 17:44:58

oc/object-c/ios哪种遍历NSArray/NSDictionary方式快?测试报告的相关文章

iOS五种本地缓存数据方式

iOS五种本地缓存数据方式 iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据全部存放在一个属性列表文件(*.plist文件)中. 2.NSUserDefaults(偏好设置),用来存储应用设置信息,文件放在perference目录下. 3.归档操作(NSkeyedArchiver),不同于前面两种,它可以把自定义对象存放在文件中. 4.coreData:coreData是苹果官

遍历NSArray, NSDictionary, NSSet的方法总结

1,for循环读取 1 NSArray: 2 NSArray *array = /*…*/ 3 for(int i=0; i<array.count; i++) 4 { 5 id object = array[i]; 6 // do sth 7 } 8 9 NSDictionary: 10 NSDictionary *dic = /*…*/ 11 NSArray *keys = [dic allKeys]; 12 for(int i=0; i<keys.count; i++) 13 { 14

iOS - 数组与字典(NSArray &amp; NSDictionary)

1. 数组的常用处理方式 //--------------------不可变数组 //1.数组的创建 NSString *s1 = @"zhangsan"; NSString *s2 = @"lisi"; NSString *s3 = @"wangwu"; //(1) NSArray *array1 = [[NSArray alloc] initWithObjects:s1,s2,s3, nil]; NSLog(@"%@",a

转---IOS 四种保存数据的方式!

在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.例如对Possession对象归档保存.

iOS 四种保存数据的方式!

在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.例如对Possession对象归档保存.

IOS 四种保存数据的方式

在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.例如对Possession对象归档保存.

iOS 两种调用拨打电话方式

iOS常用的打电话方式 第一种: [[UIApplicationsharedApplication] openURL:[NSURLURLWithString:@"tel://1008611"]]; 第二种: UIWebView *webView; if (webView == nil) { webView = [[UIWebView alloc] init]; } NSString *phoneStr = [NSString stringWithFormat:@"tel://

另一种遍历Map的方式: Map.Entry 和 Map.entrySet()

源网址: http://blog.csdn.net/mageshuai/article/details/3523116 今天看Think in java 的GUI这一章的时候,里面的TextArea这个例子在遍历Map时用到了Map.Entry 和 Map.entrySet() ,记得只见过Map.KeySet()和values()这两个方法,于是到API中一看,Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是一个接口

[转]另一种遍历Map的方式: Map.Entry 和 Map.entrySet()

转自: http://blog.csdn.net/mageshuai/article/details/3523116 今天看Think in java 的GUI这一章的时候,里面的TextArea这个例子在遍历Map时用到了Map.Entry 和 Map.entrySet() ,记得只见过Map.KeySet()和values()这两个方法,于是到API中一看,Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是一个接口,