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@標記位”實現)。

__________________________________________________________________________
本文現已同步發布到微信公眾號“老歐說安卓”,打開微信掃一掃下面的二維碼,或者直接搜索公眾號“老歐說安卓”添加關注,更快更方便地閱讀技術干貨。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM