踩坑记录 forEach和for in对比
forEach和for in对比
文章思路来自一次dart的踩坑经历,为了下次使用不再纠结。 既然forEach是基于for in (增强型for循环)的封装,那么 forEach 会比 for in 好用吗?
了解forEach、for in
forEach 和 for in 是通过 Iterator 进行遍历 比较下 forEach 的源码,可以看到 forEach 是基于for in (增强型for循环) 的封装,通过回调的方式执行代码块。那么为什么要做这一层封装呢?
// dart void forEach(void f(E element)) { for (E element in this) f(element); }
// java default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
应用场景?哪个好用?
我们来康康使用场景
void fun(List<Element> list) { list.forEach((element) ->{ // TODO // return; 返回给回调函数,也就是上面源码的f()和action 默认只能为void // 并且不能执行break;跳出 }); }
void fun(List<Element> list) { for (Element element : list) { // TODO // return; 返回到fun函数 // 可以执行break;跳出循环 } }
可以看到在功能上,明显for in支持的场景更丰富,那forEach的优势呢? 目前想到的场景是,在单线程模型中(如dart)在回调函数里进行异步请求,并且这些请求可以并发的执行,那么forEach的效率就会优于for in。(不可以并发的请求,谨慎使用,谨防踩坑)
dart 踩坑经历
在 dart 中,异步回调最常用的场景就是 await 等待事件返回,继续执行接下来的代码 下面来看两段代码,两段代码分别在子块中执行异步函数,并等待。那么他们的结果会是一样的吗?
Future<void> test1() async { print(start); var list = [5,4,3,2,1]; list.forEach((element) async { await futurePrint(element); }); print(end); } //输出 //start //end //1 //2 //3 //4 //5 Future<void> test2() async { print(start); var list = [5,4,3,2,1]; for(var t in list) { await futurePrint(t); } print(end); } //输出 //start //5 //4 //3 //2 //1 //end Future<void> futurePrint(int num) async { await Future.delayed(Duration(seconds: num)); print(num); }
结果说明了forEach虽然在子块中添加了await关键字,但是并没有等待,也就是说 子代码块(回调函数)是并行的,而for in则是顺序执行。 那么问题出在哪里了? 我们来看下async关键字的位置 对的,其实for in的await是作用于整个函数的,而forEach里的await是作用于回调函数,也就是源码中的f(E element)。它可以保证在整个回调函数里的执行顺序是有序的。
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
springboot 添加文件记录日志