for循环、快速循环forin、迭代器 NSEnumerator、迭代器的block形式 [array enumeratorObjectsUsingBlock^(id obj, NSUInteger index, BOOL *stop){}]
本文从遍历元素的效率和删除元素两个方面比较四种遍历方式。
遍历效率
测试代码如下:
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
long long length = 1000000;
for (NSInteger i = 0; i < length; i++) {
ZJZTest *test = [[ZJZTest alloc] init];
test.name = [NSString stringWithFormat:@"name - %ld", i];
[array addObject:test];
}
NSLog(@"循环次数 %lld", length);
//普通for循环
NSInteger count = array.count;
NSDate *startTime = [NSDate now];
for (NSInteger i = 0; i < count; i++) {
ZJZTest *test = array[i];
test.name = [NSString stringWithFormat:@"%@ + test", test.name];
}
NSDate *endTime = [NSDate now];
NSLog(@"for 所用时间:%.0f", [endTime timeIntervalSinceDate:startTime] * 1000);
//快速循环遍历forin
startTime = [NSDate now];
for (ZJZTest *test in array) {
test.name = [NSString stringWithFormat:@"%@ + test", test.name];
}
endTime = [NSDate now];
NSLog(@"forin 所用时间:%.0f", [endTime timeIntervalSinceDate:startTime] * 1000);
//迭代器NSEnumerator
NSEnumerator *enumerator = [array objectEnumerator];
id obj = nil;
startTime = [NSDate now];
while (obj = [enumerator nextObject]) {
ZJZTest *test = (ZJZTest *)obj;
test.name = [NSString stringWithFormat:@"%@ + test", test.name];
}
endTime = [NSDate now];
NSLog(@"NSEnumerator 所用时间:%.0f", [endTime timeIntervalSinceDate:startTime] * 1000);
//迭代器的block形式实现
startTime = [NSDate now];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
ZJZTest *test = obj;
test.name = [NSString stringWithFormat:@"%@ + test", test.name];
}];
endTime = [NSDate now];
NSLog(@"enumerateObjectsUsingBlock 所用时间:%.0f", [endTime timeIntervalSinceDate:startTime] * 1000);
结果对比:
3.jpg 2.jpg 1.jpg
对比可以看出:
1、快速遍历forin的效率始终比普通for循环高。
2、NSEnumerator和enumerateObjectsUsingBlock的效率始终相差无几。
3、随着遍历次数的增加forin的效率明显高于for、NSEnumerator、enumerateObjectsUsingBlock。
删除满足条件的元素
测试代码如下:
//普通for循环
for (NSInteger i = 0; i < array.count; i++) {
ZJZTest *test = array[i];
if ([test.name isEqualToString:@"test - 5"]) {
[array removeObject:test];
}
}
//快速循环遍历forin
for (ZJZTest *test in array) {
if ([test.name isEqualToString:@"test - 5"]) {
[array removeObject:test];
}
}
//迭代器NSEnumerator
NSEnumerator *enumerator = [array objectEnumerator];
id obj = nil;
while (obj = [enumerator nextObject]) {
ZJZTest *test = (ZJZTest *)obj;
if ([test.name isEqualToString:@"test - 5"]) {
[array removeObject:test];
}
}
//迭代器的block形式实现
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
ZJZTest *test = obj;
if ([test.name isEqualToString:@"test - 5"]) {
[array removeObject:test];
}
}];
结论:除了forin之外,其他三种方式都可以删除满足条件的元素,而采用forin快速循环遍历,删除满足条件的元素时会造成程序的crush。不可删除的原因,可以参照 关于Objective-C的for in
网友评论