1. 程式人生 > >Kotlin初體驗(三)- 字串 和 容器

Kotlin初體驗(三)- 字串 和 容器

字串

字串與基本資料型別轉換

基本資料型別轉String,在上一篇部落格已經講過,呼叫toString(),反過來,字串又該如何轉換成基本資料型別呢?請看下錶

字串轉換為其他資料型別的Kotlin與Java方式對比

字串轉換目標 Kotlin轉換方式 Java轉換方式
String->Int toInt( ) Integer.parseInt(字串變數)
String->Long toLong( ) Long.parseLong(字串變數)
String->Float toFloat( ) Float.parseFloat(字串變數)
String->Double toDouble( ) Double.parseDouble(字串變數)
String->Boolean toBoolean( ) Boolean.parseBoolean(字串變數)
String->Char[ ] toCharArray( ) toCharArray( )

Kotlin方式更加簡單,直接“變數.toXXX( )”即可 。

字串常用方法

當然,轉換型別只是字串最基本方法,還有更多字串處理的其他方法,例如查詢子串,替換子串,擷取指定位置的子串,按照特定字元分割子串等。在這方面,Kotlin基本相容Java的相關方法。對於子串的查詢,二者都用indexOf( )

,對於擷取指定位置子串操作,二者都呼叫substring( ),替換則為replace( ),按照特定字元分割,二者都呼叫split ( )。值得注意的是在這些方法中唯一不同的是,split的返回值,Java中split返回值是String[ ],Kotlin中,split方法返回值是String佇列,即List<String> 另外在Java中,獲取某個位置字元呼叫str.chatAt(index),Kotlin中直接可以str[index].toString( )

字串模板及其拼接

我們知道在Java中字串拼接,一般採用加號(+)強行拼接,或者String.format函式進行格式化。但是使用+ 容易和數值計算的+混淆,而後者格式化需要程式設計師牢記,如%d,%f,%s,%bd等格式轉換符,增加脫髮風險。而Kotlin恰如其分的對該痛點進行了優化,何必引入這些令人脫髮的轉換符呢?直接在字串中加入“$變數名”即可表示此處引用變數值,豈不妙哉! 直接上程式碼


        val str: String = "Hello iblade"
        var num: Int = 500
        //拼接字串直接“str $變數名”,別忘了$前加一個空格
        textView.text = "我拼接內容是 $str"
        //另外先運算,再把運算結果拼接到字串的情況,可以直接加{ },當然AS會自動生成該括號
        textView.text = "str length = ${str.length}"
        //我想列印$怎麼辦?轉義字元  ${'XXX'}  其中,XXX會被原樣輸出。
        textView.text = "美元結算為:${'$'}$num"
        //如果只對單個字元做轉義的話,還有更簡單方式直接反斜槓 \X 
        textView.text = "美元結算為:\$$num"
        

字串拼接小結:

  1. 字串拼接用“$變數名”
  2. 單個字元轉義,反斜槓+字元 “ \X ”
  3. 多個字元轉義 “ ${ ’ XXX ’ } ”

容器

容器基本操作

與Java類似,Kotlin也擁有三種基本的容器,分別是集合Set,佇列List,對映Map,然後每種容器又分為只讀可變兩種。這是為了判斷該容器,是否能進行增,刪,改等變更操作。Kotlin在對變數的修改操作很謹慎,每個變數在定義時就必須指定能否修改,比如新增val表示不能修改,只有var時才能修改。容器預設均為只讀容器,如需修改該容器,則需要加上Mutable字首形成新的容器,如MutableList,MutableSet,MutableMap,只用可變容器才能增刪改。 Set,List,Map同屬於容器,當然也有一些共同方法,如下:

  • isEmpty : 判斷該容器是否為空
  • isNotEmpty : 判斷該容器是否非空
  • clear :清空該容器
  • contains : 判斷容器是否包含指定元素
  • iterator : 獲取容器迭代器
  • count : 獲取容器元素個數,也可以通過size屬性獲取

另外,Kotlin允許在宣告容器時進行賦值,就像陣列那樣,這是Java中無法做到的。 不同容器初始化賦值方法分別如下:

Kotlin的容器 容器名稱 初始化方法
只讀集合 Set setOf
只讀佇列 List listOf
只讀對映 Map mapOf
可變集合 MutableSet mutableSetOf
可變佇列 MutableList mutableListOf
可變對映 MutableMap mutableMapOf

例如:

        var season: List<String> = listOf("春", "夏", "秋", "冬")
        var age: MutableList<String> = mutableListOf("1", "2", "3")  

Set/MutableSet

特性:(對應Java中的Set)

  1. 元素無序儲存,無法通過下標訪問
  2. 元素唯一,不重複,hashcode校驗是否相同元素,重複則覆蓋

Set預設只讀,就不再展開講了。針對MutableSet研究一下; Mutable新增的元素,不知道具體位置,所以無法修改,可以用remove刪除指定元素。

三種遍歷

for-in迴圈、iterator,forEach for-in和iterator的用法與java一樣,都很簡單。重點說說forEach: 前兩種遍歷均脫胎於Java,程式碼書寫上不夠精煉,為了將程式碼精練到極致,Kotlin創造了forEach方法,明確指定該方法就是要依次遍歷容器內元素,forEach採用匿名函式形式,內部使用it代表每個元素。具體看程式碼

        val topSchool: Set<String> 
        	= setOf("清華大學", "北京大學", "河南工業大學", "河南大學", "南開大學")
       //for-in
        btnClick.setOnClickListener {
            var temp = ""
            //使用for-in語句取出容器中每條記錄
            for (item in topSchool) {
                temp = "$temp 校名:$item\n"
            }
            textView.text = "中國TOP${topSchool.size}名校排行榜:\n $temp"
        }
		//iterator
        btnClick.setOnClickListener {
            var temp = ""
            val iterator = topSchool.iterator()
            while (iterator.hasNext()) {
                val item = iterator.next()
                temp = "$temp 校名:$item\n"
            }
            textView.text = "中國TOP${topSchool.size}名校排行榜:\n $temp"
        }
		//forEach
        btnClick.setOnClickListener {
            var temp = ""
            //forEach內部使用it代替每個元素
            topSchool.forEach { temp = "$temp 校名:$it\n" }
            textView.text = "中國TOP${topSchool.size}名校排行榜:\n $temp"
        }
    }

在這裡插入圖片描述 列印結果: 在這裡插入圖片描述

Set諸多不足,根本原因是無序,例如一旦新增,無法改值,不能根據位置找元素等。實際開發中,用到Set/MutableSet的機會還是挺少的。

List/MutableList:

list/MutableList 有序有下標,和Java中List一樣,使用頻率很高,常用方法有:get/set/add/removeAt等;

遍歷

list的遍歷方法除了上述三種外,多了一種下標迴圈遍歷

        val topUniversity: List<String> = listOf("清華大學", "北京人大學", "河南工業大學", "河南大學", "南開大學")

        btnClick.setOnClickListener {
            var desc = ""
            //indices是佇列下標陣列
            for (index in topUniversity.indices) {
                val item = topUniversity[index]
                desc = "$desc 校名:$item\n"
            }
            textView.text = "中國TOP${topUniversity.size}名校排行榜:\n $desc"
        }

排序操作:sortBy / sortByDescending (升序/降序)

  • reversed–相反順序;
  • sorted–自然排序(升序);
  • sortedBy–根據方法處理結果進行自然(升序)排序;
  • sortedDescending–降序排序;
  • sortedByDescending–根據方法處理結果進行降序排序;

        val topUniversity: MutableList<String> = mutableListOf("清華大學", "MIT", "河南工業大學", "河南大學", "南開大學")
        var sortAsc = true

        btnClick.setOnClickListener {
            if (sortAsc) {
                topUniversity.sortBy { it.length }
            } else {
                topUniversity.sortByDescending { it.length }
            }
            var temp = ""
            topUniversity.forEach { temp = "$temp 校名: $it\n" }
            textView.text = "名牌大學TOP${topUniversity.size}按照\"${if (sortAsc) "升序" else "降序"}\"重新排名:\n$temp"

            sortAsc = !sortAsc
        }

在這裡插入圖片描述在這裡插入圖片描述

**注意:**新版kotlin需要呼叫sorted()這樣帶"ed"字尾的方法才能返回List,而sort()是返回Unit。那麼這兩種方法還有哪些區別,或者說分別在什麼場景下使用?

還是以sort為例,sorted()處理過程中會新建臨時的List來儲存結果資料,對原來的呼叫者List不會做任何改變,所以需要將新建的物件返回;而sort()是在原來的List基礎上進行元素順序的調整,不會新建物件,所以不需要返回List。

總數操作

方法作用:

  • any–判斷集合中是否有滿足條件 的元素;

  • all–判斷集合中的元素是否都滿足條件;

  • count–查詢集合中滿足條件的元素個數;

  • fold–在給定初始值的基礎上,從第一項到最後一項進行累加;

  • foldRight–在給定初始值的基礎上,從最後一下到第一項進行累加,與fold只是的方向不同;

  • forEach–迴圈遍歷元素,元素是it,可對每個元素進行相關操作;

  • forEachIndexed–迴圈遍歷元素,同時得到元素index(下標);

  • max–查詢最大的元素,如果沒有則返回null;

  • maxBy–獲取方法處理後返回結果最大值對應的那個元素的初始值,如果沒有則返回null;

  • min–查詢最小的元素,如果沒有則返回null;

  • minBy–獲取方法處理後返回結果最小值對應那個元素的初始值,如果沒有則返回null;

  • none–判斷集合中是否都不滿足條件,是則返回true;

  • reduce–與fold區別在於沒有初始值,或者說初始值為0,從第一項到最後一項進行累加;

  • reduceRight–從最後一項到第一項進行累加,與reduce只是方向的不同;

  • sumBy–獲取方法處理後返回結果值的總和;

過濾操作:

  • drop–返回去掉前n個元素後的列表;

  • dropWhile–返回從第一項起,去掉滿足條件的元素,直到不滿足條件的一項為止;

  • dropLastWhile–返回從最後一項起,去掉滿足條件的元素,直到不滿足條件的一項為止;

  • filter–過濾掉所有不滿足條件的元素;

  • filterNot–過濾掉所有滿足條件的元素;

  • filterNotNull–過濾掉所有值為null的元素;

  • slice–過濾掉非指定下標的元素,即保留下標對應的元素過濾List中指定下標的元素(比如這裡只保留下標為1,3,4的元素),當過濾list中有元素值大於目標List大小時會出現異常;

  • take–返回從第一個開始的n個元素;

  • takeLast–返回從最後一個開始的n個元素;

  • takeWhile–返回不滿足條件的下標前面的所有元素的集合;

對映操作:

方法作用:

  • flatMap–合併兩個集合,可以在合併的時候對迭代元素值it多想要的操作;

  • groupBy–將集合中的元素按照某個條件分組,返回Map;

  • map–將集合中的元素通過某個方法轉換後的結果存到一個集合中;

  • mapIndexed–除了得到轉換後的結果,還可以拿到index(下標);

  • mapNotNull–執行方法轉換前過濾掉為null的元素;

元素操作:

contains–判斷集合中是否有指定元素,有則返回true;

elementAt–查詢下標對應的元素,如果下標越界會拋IndexOutOfBoundsException異常; elementAtOrElse–查詢下標對應元素,如果越界會根據方法返回預設值(最大下標經方法後的值); elementAtOrNull–查詢下標對應元素,越界會返回Null;

first–返回符合條件的第一個元素,沒有則會拋NoSuchElementException異常; firstOrNull–返回符合條件的第一個元素,沒有返回null;

indexOf–返回指定下標的元素,沒有返回-1; indexOfFirst–返回第一個符合條件的元素下標,沒有返回-1; indexOfLast–返回最後一個符合條件的元素下標,沒有返回-1;

last–返回符合條件的最後一個元素,沒有則會拋NoSuchElementException異常; lastIndexOf–返回符合條件的最後一個元素,沒有返回-1; lastOrNull–返回符合條件的最後一個元素,沒有返回null;

single–返回符合條件的單個元素,如有沒有符合的或符合超過一個分別會拋NoSuchElementException或IllegalArgumentException異常; singleOrNull–返回符合條件的單個元素,如有沒有符合或超過一個,返回null;

可以看到,容易出現異常的操作Kotlin會給出另一個安全呼叫的替代,如first與firstOrNull。

生產操作:

方法作用:

  • partition–根據判斷條件是否成立,拆分成兩個Pair;

  • plus–合併兩個List,可以用"+"替代;

  • zip–兩個集合按照下標組合成一個個的Pair塞到集合中返回;

  • unzip–將包含多個Pair的List轉換成含List的Pair;

  • Pair物件的資料組成形式為(first, secord),即Pair(1, 2).first可以取出資料1。

注意:文件和網上一些老的資料還提到了merge操作,編碼時提示找不到符號,查資料發現從Kotlin 1.0 Beta 2後的版本開始就棄用了。

Map/MutableMap:

map與Java中類似: containsKey / containsVaule 用於判斷是否包含鍵或值 初始化賦值時,鍵值對有兩種方式:“鍵名 to 鍵值” 和 “Pair(鍵名,鍵值)” 遍歷三種形式類似,需要說明一點是,forEach需要不低於API 24以上版本才支援: 在這裡插入圖片描述