琐碎的想法(五)for 的前世今生
for
起因
记得大学上C语言的课,第一次遇到的问题就是循环结构里面的 for。
选择结构的 if 非常易懂,和日常生活的判断没有区别。
循环结构的 while 同样比较好理解。
本质上是一个判断
- 如果为真,继续循环。
- 如果不假,则退出循环。
而 for 会稍微复杂一些。
for (init-expr; test-expr; update-expr)
body-statement
- 初始化表达式只执行一次
- 判断表达式执行
- 判断为真执行循环体
- 判断为假退出循环体
- 执行更新表达式
在实际的语义等同于(唯一区别是init-expr一个是内部变量,一个是外部变量)
init-expr
while (test-expr) {
body-statement
update-expr
}
那么我们为什么要设计一个不那么好理解的循环结构呢?
因为这时候才入了编程的门————抽象,以及约定。
如果我们再往底层挖,会发现在汇编语言中是不存在while、for 关键字的。
最开始的程序总是从左到右,从上到下一条路走到黑的。
后面编程人员意识到编写重复的代码过于麻烦才创造了 loop 。
所以最开始需要人工写一个for或者while循环。
while 好理解在于和自然语言(英语)完全符合。
当 条件满足 时, {
执行 流程;
}
而 for 循环的好处在于规范了 while 的使用。
- 初始化语句(init-expr)一般只用于循环,所以放在内部,便于回收变量。
- 循环条件(test-expr)一般配合更新语句一起使用(update-expr),实现循环有限次数。
- 三者的拆分使编写大段的循环或者嵌套循环时,更易读。
// 传统while循环
int i = 0;
while (i < 10) {
handleX();
i++;
int j = 0;
while (j < 5) {
handleY();
j++;
}
}
// for循环
for (int i = 0; i < 10; i++) {
handleX();
for (int j = 0; j < 5; j++) {
handleY();
}
}
所以 for 循环的出现也意味着编程人员开始在意的不仅仅是功能,而且看重可读性。
然而这并不会被满足。
之后还出现了
- 增强
for,部分语言的for-each,for...in。 lamdba表达式中的forEach()方法。
注意:以下按 Java 实现的 foreach 举例。(其他编程语言不太熟悉)
增强 for
foreach 的规则
- 所有使用
foreach的集合都必须实现Iterable接口 - 通过
iterator()获取iterator对象 - 通过
iterator.hasNext()判断是否存在元素。 - 通过
iterator.next()获取下一个元素。 - 通过
iterator.remove()移除返回的元素。(可选)
增强 for 的语法
List<String> list = Arrays.asList("1", "2", "3", "4", "5");
// for 版本
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// foreach 版本
for (String e : list) {
System.out.println(e);
}
// 去"糖"后的while版本
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
可以看出,foreach 对于 for、while 来说,好处是更加简单,符合直觉。
- 无需判断集合个数和中间变量减少代码出错可能性,统一通过
hasNext()处理。 - 不用分析每个集合类如何获取元素,统一通过
next()处理。 - 通过语法糖隐藏了
hasNext(), next()逻辑,代码更易读。
forEach()
Java 7/8 受到了函数式语言的影响,实现了更简练的写法。
// Iterable<T> 内实现的forEach
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
List<String> list = Arrays.asList("1", "2", "3", "4", "5");
// forEach()
list.forEach(i -> System.out.print(i));
// 方法引用
list.forEach(System.out::print);
可以看出,forEach()的好处显而易见。
- 代码量比
foreach更少,只关注遍历元素,甚至连元素类型都可以省略。 - 使用了方法引用后更进一步,我们关注的是这个集合执行了哪些操作,遍历每一次的含义在forEach()的方法已经体现了,甚至不需要写遍历的元素。
总结
可以看出,编程人员一直追寻的是更简单,更易读的代码。
- 他们不满足于汇编语言一遍遍的写同一行代码,创造了 while
- 不满足于 复杂或多层 while 的不可读, 创造了 for
- 不满足于 for 循环每一次定义的中间变量,创造了 foreach
- 不满足于 foreach 需要循环每一次的元素,利用了lamdba 的 Consumer, 去掉了元素。
琐碎的想法(五)for 的前世今生的更多相关文章
- Python-装饰器(语法糖)上下五千年和前世今生
装饰器上下五千年和前世今生,这里我们始终要问,装饰器为何产生?装饰器产生解决了什么问题?什么样的需求推动了装饰器的产生?思考问题的时候,始终要问,为什么要这样,而不是那样或者其他样.这里我不先说,也不 ...
- 琐碎的想法(三)对Java的批评的看法
编写本文的目的 在大环境下,Java是一个饱受争议的语言,一方面在工程上它的流行程度非常高:另一方面,越是资深的软件工程师就越容易对这个语言感到不满. 在这种情况下,博主希望每一个Java程序员能够耐 ...
- 《principles of model checking》中的离散时间马尔科夫链
<principles of model checking>中的离散时间马尔科夫链 说明:此文为我自学<principles of model checking>第十章内容的笔 ...
- Angular2+ 使用 Protractor 与 Modify Header Value (HTTP Headers) 插件 完成 Windows Authorization 验证
入职新公司第二周,接到了一个E2E测试的任务,两天的时间把所有的测试条件都写完了,结果剩下三天都卡在了Windows Authorization验证这里. 先说一下公司项目Authorize的逻辑 第 ...
- 一个想法(续五):IT联盟创业计划:现阶段进度公示、疑问解答及进行中的计划
前言: 首先今天是元宵节,先祝大伙元宵节快,单纯的快乐! 然后看看开展中的计划: IT联盟创业计划众筹发起:一个想法(续三):一份IT技术联盟创业计划书,开启众筹创业征程 IT联盟创业计划众筹进度:一 ...
- Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...
- JVM(五)垃圾回收器的前世今生
全文共 2195 个字,读完大约需要 8 分钟. 如果垃圾回收的算法属于内存回收的方法论的话,那本文讨论的垃圾回收器就属于内存回收的具体实现. 因为不同的厂商(IBM.Oracle),实现的垃圾回收器 ...
- JavaScript的前世今生
和CSS一样,JavaScript在各浏览器下并非完全一致,它所带来的兼容性问题时常困扰着我们,以至于现在“能否处理流行浏览器的兼容性问题”成为了检验一个程序员是否合格的标准之一.了解JavaScri ...
- JavaScript 异步编程的前世今生(上)
前言 提到 JavaScript 异步编程,很多小伙伴都很迷茫,本人花费大约一周的业余时间来对 JS 异步做一个完整的总结,和各位同学共勉共进步! 目录 part1 基础部分 什么是异步 part2 ...
- MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信
MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...
随机推荐
- 9.channels layers
settings.py配置 # 存储在内存里 CHANNEL_LAYERS = { "default": { "BACKEND": "channels ...
- 题解 P3395 路障
前言 没想到这是\(\sf {tgD1T1}\)难度-- 题目大意 有一个\(n\times n\) 的棋盘,有\(2n-2\) 个路障,在第\(i\) 秒会在\((x_i,y_i)\) 放置路障.求 ...
- disk磁盘分区软件使用教程,磁盘扩容无损备份
前几天,因为我的笔记本电脑C盘D盘全红了,趁着双11固态降价,赶紧买了一张三星980 500g 给我的拯救者插上了,加上原来的500g,总共1T,已经够用了. 不得不说拯救者系列预留的1个M.2固态插 ...
- Django系列---开发二
django.contrib.auth Django的用户验证框架,可以快速实现用户信息验证.登录.登出等用户操作 from django.contrib.auth import authentica ...
- VBA工程设置密码
VBA 工程设置密码 Alt + F11,进入程序界面: 工具---> VBAProject属性---> 保护---> 查看时锁定工程前打勾,并在下面的密码区输入密码.
- Springboot结构梳理
springboot各层关系梳理 1.基本流程 View层-->Controller层(响应用户请求):导入 service层,调用你service方法,controller通过接受前端传来的参 ...
- Java安全之CC4,5,7
前言 前边已经将CC链中的关键部分学习差不多,接下来就是一些扩展思路, CC4 ObjectInputStream.readObject() PriorityQueue.readObject() Pr ...
- Python中 or、and 的优先级
上式可以看出 先看 and 输出才为 ture 因此 优先级 and>or
- i春秋GetFlag
进去是个提示界面,提示我们这是个迷你文件管理系统,我们需要登录然后下载文件再获得flag. 然后我们查看源码,没什么信息,点login进去查看源码,没什么信息 下方出现了一个substr(md5(ca ...
- 关于CSDN博客上传图片的接口研究
代码实现 import requests from requests_toolbelt import MultipartEncoder import urllib.parse fields = { ' ...