博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
oc/object-c/ios哪种遍历NSArray/NSDictionary方式快?测试报告
阅读量:6695 次
发布时间:2019-06-25

本文共 3974 字,大约阅读时间需要 13 分钟。

做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语法会对容器里面的元素的内存地址建立一个缓冲,遍历的时候从缓冲直接取得元素的地址而不是通过调用方法来获取,所以效率比较高。另外,这也是不能在循环体中修改容器元素的原因之一。

转载地址:http://qmpoo.baihongyu.com/

你可能感兴趣的文章
JDK源码阅读(一) ArrayList
查看>>
Quartz1.8.5例子(六)
查看>>
leetcode524
查看>>
leetcode806
查看>>
(29)odoo的可用小图标
查看>>
MVC ViewBag传值
查看>>
通过面试题学习零散知识:Java面试题整理
查看>>
达成目标5步法则——雷达里奥/核聚
查看>>
可能是最简单的 区块链入门教程——阮一峰
查看>>
Linux中使用iptables开放特定端口
查看>>
AC日记——无线网络发射器选址 洛谷 P2038
查看>>
CentOS虚拟机通过主机网络上网
查看>>
ListView内容动态刷新
查看>>
秘密袭击「九省联考 2018」
查看>>
美团在线编程2016---字符串
查看>>
Android Layout XML属性
查看>>
Redis架构设计
查看>>
Programming Ability Test学习 1026. 程序运行时间(15)
查看>>
implicit和explicit的基本使用
查看>>
我们一起学习WCF 第六篇文件传输
查看>>