琐碎的想法(五)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 ...
随机推荐
- ciscn 2022 misc 部分wp
目录 everlasting_night ez_usb everlasting_night 提示是注意png数据块 然后注意图片通道数据可以用来lsb解码 下载是一张图片,尝试几种方法之后没有太大 ...
- CSS动画-transition/animation
HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...
- Java注解与原理分析
目录 一.注解基础 二.注解原理 三.常用注解 1.JDK注解 2.Lombok注解 四.自定义注解 1.同步控制 2.类型引擎 五.参考源码 使用的太多,被忽略的理所当然: 一.注解基础 注解即标注 ...
- vue3路由的使用
一.路由的概要 1.1.什么是路由? 路由就是一组映射关系,根据不同的 url 地址展示不同的内容或页面(key-value): key为路径,value可能是function或component 路 ...
- 2022春每日一题:Day 33
题目:[USACO 6.1.3] Cow XOR 没找到这题具体网址,这个题就是求最大异或区间(总长度尽量小,右端点尽量大) 嗯很显然一个[l,r]的异或和=s[r]s[l-1],那么现在有了优秀的n ...
- Go语言核心36讲49
我们在上一篇文章中简单地讨论了网络编程和socket,并由此提及了Go语言标准库中的syscall代码包和net代码包. 我还重点讲述了net.Dial函数和syscall.Socket函数的参数含义 ...
- redis五种数据结构详解
5.相关介绍和命令 5. redis是单线程+多路io复用技术 多路复用是指使用一个线程来检查多个文件描述符的就绪状态,比如调用select和poll函数,传入多个文件毛舒服,如果有一个文件描述符就绪 ...
- PHY驱动调试之 --- MDIO/MDC接口22号和45号条款(一)
最近在调试一款Phy的驱动,从没有任何头绪到略有了解经历了太多的痛苦,于是决定写这个系列篇记录一下.特别感谢无数优秀的博主无私奉献很多优秀的博文给予了我很大的帮助.在这个系列篇中,我也会转载部分优秀的 ...
- elasticsearch bucket 之rare terms聚合
目录 1.背景 2.需求 3.前置准备 3.1 准备mapping 3.2 准备数据 4.实现需求 4.1 dsl 4.2 java代码 4.3 运行结果 5.max_doc_count 和 sear ...
- SPFA和链式前向星
链式前向星 一种存储图的数据结构 建立一个结构体和一个数组加一个变量,这里的to代表边\((u,v)\)中的\(v\)结点,而\(edge\)数组的索引\(idx\)代表\(u\),其中\(w\)代表 ...