for

起因

记得大学上C语言的课,第一次遇到的问题就是循环结构里面的 for

选择结构的 if 非常易懂,和日常生活的判断没有区别。

循环结构的 while 同样比较好理解。

本质上是一个判断

  • 如果为真,继续循环。
  • 如果不假,则退出循环。

for 会稍微复杂一些。

for (init-expr; test-expr; update-expr)
body-statement
  1. 初始化表达式只执行一次
  2. 判断表达式执行
    • 判断为真执行循环体
    • 判断为假退出循环体
  3. 执行更新表达式

在实际的语义等同于(唯一区别是init-expr一个是内部变量,一个是外部变量)

    init-expr
while (test-expr) {
body-statement
update-expr
}

那么我们为什么要设计一个不那么好理解的循环结构呢?

因为这时候才入了编程的门————抽象,以及约定。

如果我们再往底层挖,会发现在汇编语言中是不存在whilefor 关键字的。

最开始的程序总是从左到右,从上到下一条路走到黑的。

后面编程人员意识到编写重复的代码过于麻烦才创造了 loop

所以最开始需要人工写一个for或者while循环。

while 好理解在于和自然语言(英语)完全符合。

    当 条件满足 时, {
执行 流程;
}

for 循环的好处在于规范了 while 的使用。

  1. 初始化语句(init-expr)一般只用于循环,所以放在内部,便于回收变量。
  2. 循环条件(test-expr)一般配合更新语句一起使用(update-expr),实现循环有限次数。
  3. 三者的拆分使编写大段的循环或者嵌套循环时,更易读。
// 传统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 循环的出现也意味着编程人员开始在意的不仅仅是功能,而且看重可读性。

然而这并不会被满足。

之后还出现了

  1. 增强 for,部分语言的for-each,for...in
  2. lamdba 表达式中的 forEach() 方法。

注意:以下按 Java 实现的 foreach 举例。(其他编程语言不太熟悉)

增强 for

foreach 的规则

  1. 所有使用 foreach 的集合都必须实现 Iterable 接口
  2. 通过 iterator() 获取 iterator 对象
  3. 通过 iterator.hasNext() 判断是否存在元素。
  4. 通过 iterator.next() 获取下一个元素。
  5. 通过 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 来说,好处是更加简单,符合直觉。

  1. 无需判断集合个数和中间变量减少代码出错可能性,统一通过 hasNext() 处理。
  2. 不用分析每个集合类如何获取元素,统一通过 next() 处理。
  3. 通过语法糖隐藏了 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()的好处显而易见。

  1. 代码量比 foreach 更少,只关注遍历元素,甚至连元素类型都可以省略。
  2. 使用了方法引用后更进一步,我们关注的是这个集合执行了哪些操作,遍历每一次的含义在forEach()的方法已经体现了,甚至不需要写遍历的元素。

总结

可以看出,编程人员一直追寻的是更简单,更易读的代码。

  • 他们不满足于汇编语言一遍遍的写同一行代码,创造了 while
  • 不满足于 复杂或多层 while 的不可读, 创造了 for
  • 不满足于 for 循环每一次定义的中间变量,创造了 foreach
  • 不满足于 foreach 需要循环每一次的元素,利用了lamdba 的 Consumer, 去掉了元素。

琐碎的想法(五)for 的前世今生的更多相关文章

  1. Python-装饰器(语法糖)上下五千年和前世今生

    装饰器上下五千年和前世今生,这里我们始终要问,装饰器为何产生?装饰器产生解决了什么问题?什么样的需求推动了装饰器的产生?思考问题的时候,始终要问,为什么要这样,而不是那样或者其他样.这里我不先说,也不 ...

  2. 琐碎的想法(三)对Java的批评的看法

    编写本文的目的 在大环境下,Java是一个饱受争议的语言,一方面在工程上它的流行程度非常高:另一方面,越是资深的软件工程师就越容易对这个语言感到不满. 在这种情况下,博主希望每一个Java程序员能够耐 ...

  3. 《principles of model checking》中的离散时间马尔科夫链

    <principles of model checking>中的离散时间马尔科夫链 说明:此文为我自学<principles of model checking>第十章内容的笔 ...

  4. Angular2+ 使用 Protractor 与 Modify Header Value (HTTP Headers) 插件 完成 Windows Authorization 验证

    入职新公司第二周,接到了一个E2E测试的任务,两天的时间把所有的测试条件都写完了,结果剩下三天都卡在了Windows Authorization验证这里. 先说一下公司项目Authorize的逻辑 第 ...

  5. 一个想法(续五):IT联盟创业计划:现阶段进度公示、疑问解答及进行中的计划

    前言: 首先今天是元宵节,先祝大伙元宵节快,单纯的快乐! 然后看看开展中的计划: IT联盟创业计划众筹发起:一个想法(续三):一份IT技术联盟创业计划书,开启众筹创业征程 IT联盟创业计划众筹进度:一 ...

  6. Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介

    Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...

  7. JVM(五)垃圾回收器的前世今生

    全文共 2195 个字,读完大约需要 8 分钟. 如果垃圾回收的算法属于内存回收的方法论的话,那本文讨论的垃圾回收器就属于内存回收的具体实现. 因为不同的厂商(IBM.Oracle),实现的垃圾回收器 ...

  8. JavaScript的前世今生

    和CSS一样,JavaScript在各浏览器下并非完全一致,它所带来的兼容性问题时常困扰着我们,以至于现在“能否处理流行浏览器的兼容性问题”成为了检验一个程序员是否合格的标准之一.了解JavaScri ...

  9. JavaScript 异步编程的前世今生(上)

    前言 提到 JavaScript 异步编程,很多小伙伴都很迷茫,本人花费大约一周的业余时间来对 JS 异步做一个完整的总结,和各位同学共勉共进步! 目录 part1 基础部分 什么是异步 part2 ...

  10. MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信

    MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...

随机推荐

  1. ciscn 2022 misc 部分wp

    ​ 目录 everlasting_night ez_usb everlasting_night 提示是注意png数据块 然后注意图片通道数据可以用来lsb解码 下载是一张图片,尝试几种方法之后没有太大 ...

  2. python实现多接口翻译软件

    本实验用pyqt5做了一个小软件,里面使用了市面上主流的6种翻译软件接口:谷歌.百度.有道.金山词霸.腾讯.必应,界面如图所示: 以下是程序代码: import time,sys,os,hashlib ...

  3. 十、RHEL Podman命令

    Podman介绍 Podman 是一个开源的容器运行时项目,可在大多数 Linux 平台上使用.Podman 提供与 Docker 非常相似的功能.正如前面提到的那样,它不需要在你的系统上运行任何守护 ...

  4. linux-web基础

    web基础 [TOC] 网上冲浪 网上冲浪:在Internet互联网上获取各种信息,进行工作.娱乐,在英文中上网是" surfing the internet",因"su ...

  5. 线上kafka消息堆积,consumer掉线,怎么办?

    线上kafka消息堆积,所有consumer全部掉线,到底怎么回事? 最近处理了一次线上故障,具体故障表现就是kafka某个topic消息堆积,这个topic的相关consumer全部掉线. 整体排查 ...

  6. CH58X/CH57X/V208 Observer(观察者)例程讨论讲解

    使用的是沁恒的CH582M的Observer例程与官方的demo板. 本例程的功能是主机扫描到从机的MAC地址并打印出来. 先对宏定义进行理解讨论. 最大响应扫描数为8,在串口调试助手那里可以看到打印 ...

  7. python中的super()是什么?

    技术场景:python中的super,名为超类,可以简单的理解为执行父类的__init__函数.由于在python中不论是一对一的继承,还是一子类继承多个父类,都会涉及到执行的先后顺序的问题.那么本文 ...

  8. shell文件报错syntax error near unexpected token '$'\r''

    本来跑的好好得一个文件,在windows下修改了,然后移植到linux就报错了. 找了一圈以下是解决方案: 这种情况发生的原因是因为你所处理的文件换行符是dos格式的"\r\n" ...

  9. Selenium4+Python3系列(七) - Iframe、Select控件、交互式弹出框、执行JS、Cookie操作

    前言 突然,想把所有之前未更新的常用Api操作.演示写出来,算是对API的一种完结吧. 下面按照Api模块来做逐一介绍. 一.iframe操作 iframe识别: 语法: driver.switch_ ...

  10. java8 (jdk 1.8) 新特性——Lambda

    java8 (jdk 1.8) 新特性 --初步认识 1. 什么是lambda? 目前已知的是,有个箭头  -> 说一大段官方话,也没有任何意义 我们直接看代码: 之前我们创建线程是这样的 Ru ...