前言

从今年的4月开始入手Kotlin到现在也有几个月时间了,在Kotlin当中循环算是这个语言当中的一个特点,最近Android上用Canvas在做游戏开发,循环也是写的非常多,发现在编写多变量的For循环无从下手,最后要不就是用Java写Kotlin调用,要不就是用While循环写,终于在今天我是解决了这个痛点,所以就打算写篇文章记录一下。

基本使用

在正式学习之前咱们先从最简单的For循环开始

从0循环到100

until关键字

until关键字在使用时左侧和右侧都需要一个数值,until循环是一个左闭右开区间

for (i in 0 until 100) {println(i) // 输出: 0 ~ 99
}

最终的输出结果包含0不包含100

使用…

…在Kotlin中也是有含义的,它称为区间表达式,它表示一个左闭右闭区间,和until关键字一样在使用的时候左侧和右侧都需要一个数值

for (i in 0..100) {println(i) // 输出: 0 ~ 100
}

最终的输出结果包含0也包含100

补充

其实…关键字也可以在直接声明成一个变量,这个变量就表示一个区间。当循环的时候 循环这个变量就会循环存储在当中的区间

val test = 0..100

注意: 使用…创建的区间只能是一个升序区间,也就是从小到大,不能从大到小,如果想从大到小需要使用另外一个关键字downTo

从100循环到0

downTo关键字

Kotlin当中降序循环使用downTo关键字,一样它也是左右侧都需要一个数值

for (i in 100 downTo 0) {println(i) // 输出: 100 ~ 0
}

你会突然发现为啥是100 ~ 0而不是100 ~ 1,其实早在刚在介绍…关键字的末尾就说了。在降序循环方面downTo关键字生成的是一个左闭右闭区间

step关键字

Kotlin在循环的时候默认步长为1,想要改变步长可以使用step关键字

从0循环到10设置步长为2

for (i in 0..10 step 2) {print("${if (i == 10) i else "$i--"}") // 输出: 0--2--4--6--8--10
}

循环数组 or 列表

上述表示都是如何从一个数循环到另外一个数,实际很多情况下用到循环是拿到ArrayList这种容器里面的值。在Kotlin当中循环这些容器的操作都是很简单的

循环一个数组 or 列表

篇幅原因这里就不贴代码结果图了,专家们可以自己拿以下代码去试试

定义一个数组

val arrayList = arrayListOf(1, 2, 3, 4, 5, 6, 12, 31, 23, 123, 12, 3, 123, 2)

直接取出元素

for (i in arrayList) {println(i) // 输出: 1,2,3,4....2
}

同时循环取出索引 and 元素

同时取出元素的索引需要在循环时调用容器的withIndex()方法

for ((index, item) in arrayList.withIndex()) {println("index: $index, item: $item") // 输出: index: 0, item: 1....index: 13, item: 2
}

通过索引遍历一个数组 or 列表

有一些情况通过索引遍历,就可以这么写

for (i in 0 until arrayList.size) {println(arrayList[i]) // 输出: 1,2,3,4....2
}

这时候你会发现你的Idea会给你一个黄线警告,因为Kotlin这种情况已经给你提供好了一个扩展方法indices

for (i in arrayList.indices) {println(arrayList[i]) // 输出: 1,2,3,4....2
}

一个小说明

kotlin的for循环其实远不止去遍历数组或列表,基本日常开发用到的数据容器都可以循环遍历(只要这个容器实现了Iterable接口),篇幅原因就不继续了,专家们可以自己去试试

多变量循环

还记得前言里我说的痛点是啥吗,就是这个多变量循环,java中多变量的for循环转化成Kotlin会直接转化成while的语法,但是while会导致代码行数暴增,可读性也不太好,还创建了局部变量。

互相转化

来看一段Java多变量for循环的代码

// 转化前java
for (int i = 0, j = 100; i < 100 && j > 0; i++, j--) {System.out.println("i: " + i + ", j: " + j); // 输出: i: 0, j: 100 ~ i: 99, j: 1
}

这段代码如果让你改成Kotlin的for循环,怎么改?先不急,先转化成kotlin看看转化后是啥样的

// 转化后kotlin
var i = 0
var j = 100
while (i < 100 && j > 0) {println("i: $i, j: $j") // 输出: i: 0, j: 100 ~ i: 99, j: 1i++j--
}

这里Kotlin直接给我们转化成了while,弊端呢也说过了,就不赘述了。直接上Kotlin for的代码

for ((i, j) in (0 until 100).zip(100 downTo 0)) {println("i: $i, j: $j") // 输出: i: 0, j: 100 ~ i: 99, j: 1
}

执行结果你会发现这三个循环输出都是一样的,篇幅原因就不分别上图了,现在就介绍一下Kotlin多变量循环

定义多变量

在Kotlin的for当中呢 in关键字的前面通常用来定义循环的变量,或者用来表示被循环容器的索引or每一项元素,这里不考虑被循环容器,只考虑定义循环的变量。当需要定义多个变量时在 () 内部进行定义,每一位变量通过逗号分隔(英文逗号)。in关键字后面呢就是设置循环区间了

for((i,j)  in...){}

设置循环区间

不知道你有没有发现,其实在kotlin的for循环定义循环变量的时候都没有给它赋予初始值,而是直接指定了它需要循环的区间以及是降序循环还是正序循环,所以上面描述的in循环前面是定义的变量而不是初始值

现在来给上述定义好的循环变量设置循环区间,多个循环区间使用 .zip() 函数进行设置

for ((i, j) in (0 until 10).zip(1 until 10)) {println("i: $i, j: $j")
}

上述代码含义 i的区间为0 ~ 10的升序j的区间为1 ~ 10的升序

我们来输出看看结果

没看错吧,i的难道不应该是0 ~ 9吗,为什么到8结束了?别急,咱们先看j的循环区间1 ~ 10,没问题吧 until左闭右开,这里的j循环次数要比i循环次数少一次,所以结束了。你可能会很懵,为什么结束了难道不应该i要输出到9吗,别急,我们同样的代码用java写

for (int i = 0, j = 1; i < 10 && j < 10; i++, j++) {System.out.println("i:" + i + ", j:" + j);
}

输出结果一致,配合java一起这块代码应该就理解起来没问题了

咱们继续

三个变量 and 四个变量

有时候循环的变量有三个或者四个,这时候你会发现又无从下手了,尝试在zip().zip(),会发现给你报个错误

for((i,j,k) in (0..100).zip(0..100).zip(0..100)){} // 错误代码

Kotlin: Destructuring declaration initializer of type Pair<Pair<Int, Int>, Int> must have a ‘component3()’ function

大意就是你不能这么写,三个变量或四个变量或者更多的时候你需要使用Pair类型的值作为循环变量,Pair是一个二分元组,可以把多个值同时赋给一个变量,或者同时给多个变量赋值,有二分就还有三分元组,三分元组Triple,不过在我的学习过程中没有用上三分,貌似现在的for循环最多也只支持也二分元组 (zip()返回二分元组),如果有不对的地方欢迎知道详情的大佬补充指正,我也会第一时间修改本文章

好了那我们就开始吧

三个变量

其实改变很少,in前面依旧是两个变量,不过其中一个存储的是元组,元组内部存储着值

先上代码
for ((i, jPair) in (1..100).zip((0..100).zip(0..100)) ) {println("i: $i,  $jPair")
}

你会发现调用两个zip函数,好像咱们还没有介绍zip函数的作用蛤,船到桥头自然直,先看输出结果

你会发现输出的后面jPair变成了一个对象,其实这个时候jPair已经成了元组对象,输出对象,对象里面有两个值,我们直接输出是这样的,如果我们想要拿到其中一个值呢?这么写

for ((i, jPair) in (1..100).zip((0..100).zip(0..100))) {println("i: $i |  jPair.firstValue: ${jPair.first} |  jPair.secondValue: ${jPair.second}")
}

输出结果:

二分元组只能存储两个值,两个值都可以通过 对象.first and 对象.second来获取,现在我们再来介绍zip。

zip()介绍

Returns a list of pairs built from the elements of this collection and other collection with the same index. The returned list has length of the shortest collection.

上述的英文是在zip()函数的注释中截取下来的,大致意思就是返回索引最小的集合作为索引,两个集合取它们的交集。

是不是看完觉得很懵,没错我也一样,咱们不看注释了直接来看看源码接收的参数还有返回的参数吧

public infix fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>> {return zip(other) { t1, t2 -> t1 to t2 }
}

接收的参数需要是一个实现了Iterable接口的类型,正好在Kotlin中常用的数据存储结构其实都已经实现了这个接口,同时咱们的区间表达式也是支持的。

在看返回值,返回值返回了一个包含元组对象的列表,接下来你就可以再看看三个变量的for循环,是不是一目了然了

四个变量

四个变量就这么写,细节我也不继续赘述了,和三个变量就只有一点点区别而已

for ((iPair, jPair) in ((1..100).zip(1..100)).zip((0..100).zip(0..100))) {println("iPair: $iPair |  jPair: $jPair")
}

执行结果:

要拿取元组对象里面的值上述也讲过了,这里就不在重复了。

小结

总体来说在多变量循环的时候Kotlin还是比较复杂的,但是如果熟悉语法其实看上去还是非常简洁的,不过日常开发中很少会涉及到多变量循环,这里也只是提一嘴其实kotlin是能做到的。如果没有明白就自己写写例子,会更加清楚zip()函数的用法以及for循环在多变量的时候执行流程

循环控制

有时候我们需要对循环进行一些控制,kotlin在这方面也有它的独特之处

结构跳转表达式

和大多数语言一样Kotlin的for循环也是两个结构跳转表达式:

  • break : 终止距离最近的循环
  • continue : 跳出最近的一次循环
for (i in 0 until 10) {if (i == 5) break // 输出: 0 ~ 4
}for (i in 0 until 10) {if (i == 5) continue // 输出: 0 ~ 9
}

标签命名

标签命名算是Kotlin 循环当中很有特色的一个点了,我们可以给循环设立一个标签,然后通过结构跳转表达式操作标签对应的循环。

命名格式为: 标签名@

跳出指定标签可以这么写: break@标签名 or continue@标签名

all@ for (i in 0 until 100) {inner@ for (j in 100 downTo 0) {if (i == 60) break@innerif (j == 60) continue@allprintln("j: $j")}println("i: $i")
}

大家可以自己去试试,这里也就不贴执行结果了

总结

Kotlin的For循环我觉得总结的还算比较到位,从简单使用到多变量、遍历常用的容器,以及循环控制都总结到了。文章中如果你觉得哪里写的有问题欢迎指正,这也是我的第一篇文章,可能一些知识点描述的不是很好,不过我相信配合代码自己动手试试应该很快能理解我想表达的意思。最后谢谢您的阅读!

Kotlin For循环详解相关推荐

  1. linux中until循环的特点,Bash 中的 until 循环详解

    Bash 中的 until 循环详解 循环是编程语言的基本概念之一.当你想要一遍又一遍地运行一系列命令直到达到某个条件后终止退出时,循环很方便. 在诸如 Bash 之类的脚本语言中,循环对于自动执行重 ...

  2. [C语言] for循环详解 循环 for循环实例巧解

    前言>>> 嘿嘿,本文要讲的小方法实例使用牛客网的这道题 ↑↑↑ .怎么样!!?  ^  ^ 100% 到底是系统太假还是我写得好??? 开始>>>   题目:线段 ...

  3. java for循环教程,java入门教程:for的用法_for循环详解

    for循环详解 虽然所有循环结构都可以用while或者do...while表示,但Java提供了另一种语句 -- for循环,使一些循环结构变得更加简单. for循环执行的次数是在执行前就确定的.语法 ...

  4. java for新循环_Java for循环详解

    Java for循环详解 for 语句是应用最广泛.功能最强的一种循环语句.大部分情况下,for 循环可以代替 while 循环.do while 循环. for 语句是一种在程序执行前就要先判断条件 ...

  5. Robot Framework For循环详解

    Robot Framework For循环详解 1.普通For循环 2.在List变量内循环 3.多重嵌套循环 4.For in range循环,只指定结束 5.For in range循环,指定开始 ...

  6. php 微信小程序 循环 多选,微信小程序 for 循环详解

    1,wx:for 在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件.默认数组的当前项的下标变量名默认为index,数组当前项的变量名默认为item 事例如下: wx ...

  7. ES6的 for of 循环详解

    ES6的 for of 循环详解 其实使用ES6中的 for of 循环还是有一定的要求,就是循环的对象必须有Symbol.iterator这个属性,而且属性值一定要是一个函数. 循环的对象一定要有S ...

  8. nodejs ref操作_nodejs事件和事件循环详解

    简介 上篇文章我们简单的介绍了nodejs中的事件event和事件循环event loop.本文本文将会更进一步,继续讲解nodejs中的event,并探讨一下setTimeout,setImmedi ...

  9. JavaScript事件循环详解

    做为一个前端开发,要想深入学习JavaScript进阶知识,就不得不了解JavaScript的事件循环.JavaScript的事件循环抽象,不易理解,谁都可以说出单线程,宏任务,微任务,但大部分人只是 ...

  10. Kotlin 操作符重载详解

    本文主要内容 算术操作符重载 二元操作符重载 复合赋值操作符重载 一元操作符重载 比较操作符重载 集合相关的操作符重载 索引操作符重载 索引操作符重载Kotlin集合中的应用 in 操作符重载 区间操 ...

最新文章

  1. 玻璃上的编码喜悦(+ 10史诗般的Epigrams)
  2. 2021年4月28日 深圳头条后台开发实习面试(hr面)
  3. Apache服务器错误问题Internal Server Error
  4. python 匿名函数捕获变量值 (执行时的值)
  5. 若依前后端分离版怎样去掉登录验证码
  6. 消除ubuntu16.04自带的alt快捷键
  7. 【动画技巧】在Flash中自定义鼠标外观
  8. 第一个Spark实例:求PI值
  9. ubuntu chmsee出现乱码的解决方法
  10. 【转】UINavigationController 直接返回到第一级目录
  11. ffmpeg-0.6.3开源编码解码库,从linux下移植到windows vs2005,全部开源。
  12. 我的大学专业是计算机英语作文,我的大学计划英语作文(通用5篇)
  13. 将linux系统分区变成逻辑卷,linux运维基础知识-系统分区及LVM逻辑卷的创建
  14. latex linux 安装,Linux 安装LaTeX
  15. linux 屏幕键盘onborde,电脑虚拟键盘模拟器|On-Screen Keyboard pro(电脑屏幕键盘软件)下载 V9.0.4 官方版 - 比克尔下载...
  16. 重置IE浏览器的设置
  17. LCL三相pwm整流器(逆变器)
  18. python调用pandas保存excel
  19. UI设计中面性图标设计总结
  20. 抖音短视频的推荐机制是什么? 国仁网络资讯

热门文章

  1. JAVA:实现ClosestPair最近对算法(附完整源码)
  2. 使用 closest 和 matches 方法来检测元素是否存在某选择器
  3. Python:实现binomial distribution二项分布算法(附完整源码)
  4. Sub-Gaussian随机变量
  5. 用python爬取小说章节内容
  6. Numpy掩码数组masked arrays
  7. Redis Cluster 原生搭建(二)meet
  8. 2021年全国压岁钱排行榜,大数据告诉你哪的红包最大?
  9. JavasScript 第一天课 课后笔记 2022.3.21
  10. 【牛奶豆腐汤喝出小蛮腰】