专栏首页老欧说安卓Kotlin入门(7)循环语句的操作

Kotlin入门(7)循环语句的操作

上一篇文章介绍了简单分支与多路分支的实现,控制语句除了这两种条件分支之外,还有对循环处理的控制,那么本文接下来继续阐述Kotlin如何对循环语句进行操作。 Koltin处理循环语句依旧采纳了for和while关键字,只是在具体用法上有所微调。首先来看for循环,Java遍历某个队列,可以通过“for (item : list)”形式的语句进行循环操作。同样Kotlin也能使用类似形式的循环,区别在于把冒号“:”换成了关键字“in”,具体语句形如“for (item in list)”。下面是Kotlin对数组进行循环处理的代码例子:

    val poemArray:Array<String> = arrayOf("朝辞白帝彩云间", "千里江陵一日还", "两岸猿声啼不住", "轻舟已过万重山")
    btn_repeat_item.setOnClickListener {
        var poem:String=""
        for (item in poemArray) {
            poem = "$poem$item,\n"
        }
        tv_poem_content.text = poem
    }

上述代码的目的是将一个诗句数组用逗号与换行符拼接起来,以便在界面上展示完整的诗歌内容。拼接后的诗歌显示界面如下图所示:

注意到截图中每行诗句都以逗号结尾,这有个句点问题,因为每首绝句的第一、三行末尾才是逗号,第二、四行的末尾应该是句号;所以这个循环代码得加以改进,补充对数组下标的判断,如果当前是奇数行,则末尾加逗号;如果当前是偶数行,则末尾加句号。倘若使用Java编码,要是涉及到下标的循环,基本采取“for (初始的赋值语句; 满足循环的条件判断; 每次循环之后的增减语句)”这般形式,具体实现可参考以下的示例代码:

    for (int i=0; i<array.length; i++) {
        ...
    }

出人意料的是,Kotlin废除了“for (初始; 条件; 增减)”这个规则;若想实现上述功能,取而代之的,则为“for (i in array.indices)”语句,其中indices表示该数组对象的下标数组,每次循环都从下标数组依次取出当前元素的下标。根据该规则判断下标的数值,再分别在句尾添加逗号与句号,改造后的Kotlin代码如下所示:

    btn_repeat_subscript.setOnClickListener {
        var poem:String=""
        for (i in poemArray.indices) {
            if (i%2 == 0) {
                poem = "$poem${poemArray[i]},\n"
            } else {
                poem = "$poem${poemArray[i]}。\n"
            }
        }
        tv_poem_content.text = poem
    }

正确补充标点的诗歌显示界面如下图所示:

然而取消“for (初始; 条件; 增减)”这个规则是有代价的,因为实际开发中往往存在非同一般的需求,比如以下几种情况,Kotlin的“for (i in array.indices)”语句就无法很好地处理: 1、如何设定条件判断的起始值和终止值? 2、每次循环之后的递增值不是1的时候要怎么办? 3、循环方向不是递增而是递减,又如何是好? 4、与条件判断有关的变量不止一个,咋整? 5、循环过程中的变量,在循环结束后还能不能使用? 针对以上情况,其实Kotlin也给出了几个解决办法,代价是多了几个诸如until、step、downTo这样的关键字,具体用法见下列代码:

    // 左闭右开区间,合法值包括11,但不包括66
    for (i in 11 until 66) { ... }
    // 每次默认递增1,这里改为每次递增4
    for (i in 23..89 step 4) { ... }
    // for循环默认递增,这里使用downTo表示递减
    for (i in 50 downTo 7) { ... } 

可是这些解决办法并不完美,因为业务需求是千变万化的,并非限定在几种固定模式。同时,以上规则容易使人混淆,一旦没搞清楚until和downTo的开闭区间,在判断边界值时会产生问题。所以更灵活的解决方案是,起止数值、条件判断、循环方向与递增值都应当在代码中明确指定,“for (初始; 条件; 增减)”这个规则固然废除了,但开发者依旧能够使用while语句实现相关功能,Kotlin的while循环与Java的处理是一致的,下面是使用while进行循环判断的代码例子:

    btn_repeat_begin.setOnClickListener {
        var poem:String=""
        var i:Int = 0
        while (i < poemArray.size) {
            if (i%2 ==0) {
                poem = "$poem${poemArray[i]},\n"
            } else {
                poem = "$poem${poemArray[i]}。\n"
            }
            i++
        }
        poem = "${poem}该诗歌一共有${i}句。"
        tv_poem_content.text = poem
    }

既然while语句保留了下来,do/while语句继续保留,写法也没什么变化,采用do/while写法的代码如下所示:

    btn_repeat_end.setOnClickListener {
        var poem:String=""
        var i:Int = 0
        do {
            if (i%2 ==0) {
                poem = "$poem${poemArray[i]},\n"
            } else {
                poem = "$poem${poemArray[i]}。\n"
            }
            i++
        } while (i < poemArray.size)
        poem = "${poem}该诗歌一共有${i}句。"
        tv_poem_content.text = poem
    }

前面的循环处理其实都还中规中矩,只有内忧没有外患,但要是数组里的诗句本身就不完善,比如有空指针、有空串、有空格串、有多余串等等,此时就得进行诗句的合法性判断,如此方可输出正常的诗歌文字。合法性判断主要由两块代码组成: 1、如果发现有空指针、有空串、有空格串,则忽略此行,即使用关键字continue继续下个循环; 2、如果合法诗句达到四句,则不管是否遍历完成,直接拼好绝句并结束循环,即使用关键字break跳出循环; 加入了合法性判断的代码见下,主要演示了continue和break:

    val poem2Array:Array<String?> = arrayOf("朝辞白帝彩云间", null, "千里江陵一日还", "", "两岸猿声啼不住", "   ", "轻舟已过万重山", "送孟浩然之广陵")
    btn_repeat_continue.setOnClickListener {
        var poem:String=""
        var pos:Int=-1
        var count:Int=0
        while (pos <= poem2Array.size) {
            pos++
            if (poem2Array[pos].isNullOrBlank())
                continue
            if (count%2 ==0) {
                poem = "$poem${poem2Array[pos]},\n"
            } else {
                poem = "$poem${poem2Array[pos]}。\n"
            }
            count++
            if (count == 4)
                break
        }
        tv_poem_content.text = poem
    }

看来合法性判断用到的continue和break,Kotlin并没有做什么改进呀?这是真的吗?如果是真的,那真是图样图森破。以往我们操作多层循环的时候,有时在内层循环发现某种状况,就得跳出包括外层循环在内的整个循环。例如遍历诗歌数组,一旦在某个诗句中找到“一”字,便迅速告知外界“我中奖啦”之类的欢呼。可是这里有两层循环,如果使用Java编码,只能先跳出内层循环,然后外层循环通过判断标志位再决定是否跳出,而不能从内层循环直接跳出外层循环。现在Kotlin大笔一挥,干嘛这么麻烦,咱想跳到哪里就跳到哪里,只消给外层循环加个@标记,接着遇到情况便直接跳出到这个标记,犹如孙悟空蹦上筋斗云,想去哪就去哪,多方便。这个创意真好,省事省力省心,赶紧看看下面代码是怎么实现的:

    btn_repeat_break.setOnClickListener {
        var i:Int = 0
        var is_found = false
        outside@ while (i < poemArray.size) {
            var j:Int = 0
            var item = poemArray[i];
            while ( j < item.length) {
                if (item[j] == '一') {
                    is_found = true
                    break@outside
                }
                j++
            }
//            //如果内层循环直接跳出两层循环,那么下面的判断语句就不需要了
//            if (is_found)
//                break
            i++
        }
        tv_poem_content.text = if (is_found) "我找到'一'字啦" else "没有找到'一'字呀"
    }

总结一下,对于循环语句的操作,Kotlin仍然保留了for和while两种循环,主要区别在于:Kotlin取消了“for (初始; 条件; 增减)”这个规则,不过新增了对跳出多重循环的支持(通过“break@标记位”实现)。 点此查看Kotlin入门教程的完整目录

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android开发笔记(一百五十二)H5通过WebView上传图片

    上一篇文章介绍了WebView与JS之间的数据交互,其实就是把字符串传来传去,这对文本格式的信息传输来说倒还凑合,倘若要传输图...

    用户4464237
  • Android开发笔记(三十)SQLite数据库基础操作

    SQLite是一个小巧的嵌入式数据库,使用方便、开发简单,手机上最早由ios运用,后来android兴起同样也采用了sqlite。sqlite的多数sql语...

    用户4464237
  • Android开发笔记(三)屏幕分辨率

    在app编码中经常需要获取手机的屏幕分辨率(宽*高),原来我直接上网拷贝代码,但在使用过程中却发现诸多不便。 不便一:下面...

    用户4464237
  • 1个等式!3行代码!78倍!如何加速机器学习算法?

    众所周知,Python的for循环本质上要比C慢很多。 而且深度学习和机器学习算法严重依赖通过for循环执行的矩阵运算。

    量化投资与机器学习微信公众号
  • 数组常用循环

    用户6973020
  • 拍照总被路人甲抢镜?那就用这个项目消Ta

    项目地址:https://github.com/JiahuiYu/generative_inpainting

    昱良
  • 拍照总被路人甲抢镜?那就用这个项目消Ta

    项目地址:https://github.com/JiahuiYu/generative_inpainting

    机器之心
  • 【计算机本科补全计划】Java学习笔记(一) 安装配置 (Mac Sublime3) 红黄蓝

    正文之前 标题后面为啥要加三个字呢。蹭热度不至于,就想着,让更多人知道么。毕竟我以后也会有当爸的一天~ 要是那些人渣站在悬崖上,旁边没啥人看着,我上去踢一脚是做...

    用户1687088
  • Hacking with iOS: SwiftUI Edition - 里程碑:项目 7 - 9

    希望您觉得这些项目开始让您有所收获,不仅可以进一步提高您的SwiftUI技能,还可以教给您一些更高级的Swift。另外,当然,您还创建了两个新的SwiftUI项...

    韦弦zhy
  • 有关bash,我希望我能知晓的十件事

    小小科

扫码关注云+社区

领取腾讯云代金券