點擊這裏 > 去京東商城購買閱讀
點擊這裏 > 去天貓商城購買閱讀
本章將介紹Kotlin標準庫中的集合類,咱們將瞭解到它是如何擴展的Java集合庫,使得寫代碼更加簡單容易。若是您熟悉Scala的集合庫,您會發現Kotlin跟Scala集合類庫的類似之處。html
在講 Kotlin 的集合類以前,爲了更加深入理解爲何要有集合類,以及集合類究竟是怎麼一回事,讓咱們先來簡單回顧一下編程的本質:java
數據結構 + 算法 (信息的邏輯結構及其基本操做)程序員
咱們使用計算機編程來解決一個具體問題時,大體須要通過下列幾個步驟:算法
首先要從具體問題中抽象出一個適當的數學模型;
而後設計一個解此數學模型的算法(Algorithm);
最後編出程序、進行測試、修改直至獲得最終解答。編程
這裏面的尋求數學模型的過程,實質就是分析問題,從中提取操做的對象,並找出這些操做對象之間含有的關係的過程。創建好的模型,咱們使用數學語言來表達。設計模式
這裏的模型對應的就是數據結構。咱們用計算機編程來解決問題的關鍵就是,設計出合適的數據結構(例如,用線性表、樹、圖等)和性能良好的算法。數組
算法與數據的結構密切相關,算法無不依附於具體的數據結構,數據結構直接關係到算法的選擇和效率。一般狀況下,設計良好的數據結構能夠大大簡化算法的實現複雜度,同時能夠提高存儲效率。數據結構每每同高效的檢索算法和索引技術相關。數據結構
咱們能夠把數據結構理解爲是ADT的實現。數據結構就是現實問題模型的表達。架構
數據結構主要解決如下三個問題:app
這些邏輯關係有:集合、線性結構、樹形結構、圖形結構等。
數據的邏輯結構在計算機存儲空間的存放形式。數據的物理結構是數據結構在計算機中的映射。其具體實現的方法有: 順序(Sequence)、連接(Link)、索引(Index)、散列(Hash)等形式。
其中,順序存儲結構和鏈式存儲結構是咱們經常使用的兩種存儲結構。
順序存儲是使用元素在存儲器中的相對位置來表示數據元素之間的邏輯關係;
鏈式存儲使用指示元素存儲位置的指針(pointer)來表示數據元素之間的邏輯關係。
咱們如今不多用抽象數據類型ADT(Abstract Data Type)這個概念,其實這個概念是OO範式的前身,也是類的前身。ADT加上繼承、重載和多態性就是現代OOP編程範式中的類的概念了。咱們簡稱類爲廣義ADT的概念。
若是咱們更加廣義的來理解這裏的ADT的思想,其實各類編程語言的SDK API、全部的服務(IaaS,PaaS和SaaS等)都是一種更加廣義的ADT。
使用ADT可讓咱們更簡單地描述現實世界。例如:用線性表描述學生成績表,用樹或圖描述遺傳關係等。
咱們知道類的本質就是,對象及其關係的抽象(abstraction)。一個類一般有屬性(數據結構)和行爲(算法)。使用OO範式編程的大體過程爲:
劃分對象 → 抽象類 → 將類組織成爲層次化結構(繼承和合成) → 用類與實例進行設計和實現
等幾個階段。
數據抽象本質上講就是咱們解決現實問題的過程當中,進行創建領域模型(Domain Model)的過程。
好比說,在前一章節中,咱們介紹的程序設計語言的類型系統,本質上就是一種數據抽象。因爲計算機的結構和存儲的限制(沒法像人類大腦神經系統同樣去認知識別,並解決現實問題),人類大腦在解決實際問題過程當中,常常要計算整數、小數, 要處理英文字符、中文字符, 要持有對象(被操做的數據),要對這些對象進行諸如:查找、排序、修改、傳遞等操做。把這些問題解決中最經常使用的數據結構以及其操做算法抽象成對應的類(例如:String、Array、List、Set、Map等),這樣咱們就能夠極大的複用這些功能。而不須要咱們本身來實現諸如:字符串、數組、列表、集合、映射等這些的數據結構。一般這些最通用的數據結構,都是如今編程語言中內置的了。
內存中的存儲形式能夠分爲連續存儲和離散存儲兩種。所以,數據的物理存儲結構就有連續存儲和離散存儲兩種,它們對應了咱們一般所說的數組和鏈表。
因爲數組是連續存儲的,在操做數組中的數據時就能夠根據離首地址的偏移量直接存取相應位置上的數據,可是若是要在數據組中任意位置上插入一個元素,就須要先把後面的元素集體向後移一位爲其空出存儲空間。與之相反,鏈表是離散存儲的,因此在插入一個數據時只要申請一片新空間,而後將其中的鏈接關係作一個修改就能夠,可是顯然在鏈表上查找一個數據時就要逐個遍歷了。
考慮以上的總結可見,數組和鏈表各有優缺點。在具體使用時要根據具體狀況選擇。當查找數據操做比較多時最好用數組;當對數據集中的數據進行添加或刪除比較多時最好選擇鏈表。
集合類存放的都是對象的引用,而非對象自己,咱們一般說的集合中的對象指的是集合中對象的引用(reference)。
Kotlin的集合類分爲:可變集合類(Mutable)與不可變集合類(Immutable)。
集合類型主要有3種:list(列表)、set(集)、和 map(映射)。
列表的主要特徵是其對象以線性方式存儲,沒有特定順序,只有一個開頭和一個結尾,固然,它與根本沒有順序的集是不一樣的。
列表在數據結構中可表現爲:數組和向量、鏈表、堆棧、隊列等。
集(set)是最簡單的一種集合,它的對象不按特定方式排序,只是簡單的把對象加入集合中,就像往口袋裏放東西。
對集中成員的訪問和操做是經過集中對象的引用進行的,因此集中不能有重複對象。
集也有多種變體,能夠實現排序等功能,如TreeSet,它把對象添加到集中的操做將變爲按照某種比較規則將其插入到有序的對象序列中。它實現的是SortedSet接口,也就是加入了對象比較的方法。經過對集中的對象迭代,咱們能夠獲得一個升序的對象集合。
映射與集或列表有明顯區別,映射中每一個項都是成對的。映射中存儲的每一個對象都有一個相關的關鍵字(Key)對象,關鍵字決定了 對象在映射中的存儲位置,檢索對象時必須提供相應的關鍵字,就像在字典中查單詞同樣。關鍵字應該是惟一的。
關鍵字自己並不能決定對象的存儲位置,它須要對過一種散列(hashing)技術來處理,產生一個被稱做散列碼(hash code)的整數值,
散列碼一般用做一個偏置量,該偏置量是相對於分配給映射的內存區域起始位置的,由此肯定關鍵字/對象對的存儲位置。理想狀況 下,散列處理應該產生給定範圍內均勻分佈的值,並且每一個關鍵字應獲得不一樣的散列碼。
List接口繼承於Collection接口,元素以線性方式存儲,集合中能夠存放重複對象。Kotlin的List分爲:不可變集合類List(ReadOnly, Immutable)和可變集合類MutableList(Read&Write, Mutable)。
其類圖結構以下:
其中,Iterator
是全部容器類Collection
的迭代器。迭代器(Iterator)模式,又叫作遊標(Cursor)模式。GOF給出的定義爲:提供一種方法訪問一個容器對象中各個元素,而又不需暴露該對象的內部細節。 從定義可見,迭代器模式是爲容器而生。
咱們可使用listOf
函數來構建一個不可變的List(read-only,只讀的List)。它定義在libraries/stdlib/src/kotlin/collections/Collections.kt
裏面。關於listOf
這個構建函數有下面3個重載函數:
@kotlin.internal.InlineOnly public inline fun <T> listOf(): List<T> = emptyList() public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList() @JvmVersion public fun <T> listOf(element: T): List<T> = java.util.Collections.singletonList(element)
這些函數建立的List都是是隻讀的(readonly,也就是不可變的immutable )、可序列化的。
其中,
listOf()
用於建立沒有元素的空ListlistOf(vararg elements: T)
用於建立只有一個元素的ListlistOf(element: T)
用於建立擁有多個元素的List
咱們使用代碼示例分別來演示其用法:
首先,咱們使用listOf()
來構建一個沒有元素的空的List:
>>> val list:List<Int> = listOf() >>> list [] >>> list::class class kotlin.collections.EmptyList
注意,這裏的變量的類型不能省略,不然會報錯:
>>> val list = listOf() error: type inference failed: Not enough information to infer parameter T in inline fun <T> listOf(): List<T> Please specify it explicitly. val list = listOf() ^
由於這是一個泛型函數。關於泛型,咱們將在下一章中介紹。
其中,EmptyList
是一個 internal object EmptyList
, 這是Kotlin內部定義的一個默認空的object List類。
下面,咱們再來建立一個只有1個元素的List:
>>> val list = listOf(1) >>> list::class class java.util.Collections$SingletonList
咱們能夠看出,它其實是調用Java的java.util.Collections
裏面的singletonList
方法:
public static <T> List<T> singletonList(T o) { return new SingletonList<>(o); }
咱們再來建立一個有多個元素的List:
>>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9) >>> list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list::class class java.util.Arrays$ArrayList >>> list::class.java
它調用的是
fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()
這個函數。其中,asList
函數是Array
的擴展函數:
public fun <T> Array<out T>.asList(): List<T> { return ArraysUtilJVM.asList(this) }
而這個ArraysUtilJVM
是一個Java類,裏面實際上調用的是java.util.Arrays
和java.util.List
:
package kotlin.collections; import java.util.Arrays; import java.util.List; class ArraysUtilJVM { static <T> List<T> asList(T[] array) { return Arrays.asList(array); } }
另外,咱們還能夠直接使用arrayListOf
函數來建立一個Java中的ArrayList對象實例:
>>> val list = arrayListOf(0,1,2,3) >>> list [0, 1, 2, 3] >>> list::class class java.util.ArrayList >>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9) >>> list::class class java.util.Arrays$ArrayList
這個函數定義在libraries/stdlib/src/kotlin/collections/Collections.kt
類中:
@SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun <T> arrayListOf(): ArrayList<T> = ArrayList()
一樣的處理方式,這裏的ArrayList()
是Java中的 java.util.ArrayList
的類型別名:
@SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>
在MutableList中,除了繼承List中的那些函數外,另外新增了add/addAll、remove/removeAll/removeAt、set、clear、retainAll等更新修改的操做函數。
override fun add(element: E): Boolean override fun remove(element: E): Boolean override fun addAll(elements: Collection<E>): Boolean fun addAll(index: Int, elements: Collection<E>): Boolean override fun removeAll(elements: Collection<E>): Boolean override fun retainAll(elements: Collection<E>): Boolean override fun clear(): Unit operator fun set(index: Int, element: E): E fun add(index: Int, element: E): Unit fun removeAt(index: Int): E override fun listIterator(): MutableListIterator<E> override fun listIterator(index: Int): MutableListIterator<E> override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>
建立一個MutableList的對象實例跟List相似,前面加上前綴mutable
,代碼示例以下:
>>> val list = mutableListOf(1, 2, 3) >>> list [1, 2, 3] >>> list::class class java.util.ArrayList >>> val list2 = mutableListOf<Int>() >>> list2 [] >>> list2::class class java.util.ArrayList >>> val list3 = mutableListOf(1) >>> list3 [1] >>> list3::class class java.util.ArrayList
咱們能夠看出,使用mutableListOf
函數建立的可變集合類,實際上背後調用的是java.util.ArrayList
類的相關方法。
另外,咱們能夠直接使用Kotlin封裝的arrayListOf
函數來建立一個ArrayList:
>>> val list4 = arrayListOf(1, 2, 3) >>> list4::class class java.util.ArrayList
關於Kotlin中的ArrayList
類型別名定義在kotlin/collections/TypeAliases.kt
文件中:
@file:kotlin.jvm.JvmVersion package kotlin.collections @SinceKotlin("1.1") public typealias RandomAccess = java.util.RandomAccess @SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E> @SinceKotlin("1.1") public typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V> @SinceKotlin("1.1") public typealias HashMap<K, V> = java.util.HashMap<K, V> @SinceKotlin("1.1") public typealias LinkedHashSet<E> = java.util.LinkedHashSet<E> @SinceKotlin("1.1") public typealias HashSet<E> = java.util.HashSet<E> // also @SinceKotlin("1.1") internal typealias SortedSet<E> = java.util.SortedSet<E> internal typealias TreeSet<E> = java.util.TreeSet<E>
若是咱們已經有了一個不可變的List,而咱們如今想把他轉換成可變的List,咱們能夠直接調用轉換函數toMutableList
:
val list = mutableListOf(1, 2, 3) val mlist = list.toMutableList() mlist.add(5)
咱們以集合 val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)
爲例,使用Iterator迭代器遍歷列表全部元素的操做:
>>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9) >>> list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> val iterator = list.iterator() >>> iterator java.util.AbstractList$Itr@438bad7c >>> while(iterator.hasNext()){ ... println(iterator.next()) ... } 0 1 2 3 4 5 6 7 8 9
迭代器是一種設計模式,它是一個對象,它能夠遍歷並選擇序列中的對象,而開發人員不須要了解該序列的底層結構。迭代器一般被稱爲「輕量級」對象,由於建立它的代價小。
Kotlin中的Iterator功能比較簡單,而且只能單向移動:
(1) 調用iterator()函數,容器返回一個Iterator實例。iterator()函數是kotlin.collections.Iterable
中的函數, 被Collection繼承。
(2)調用hasNext()函數檢查序列中是否還有元素。
(3)第一次調用Iterator的next()函數時,它返回序列的第一個元素。依次向後遞推,使用next()得到序列中的下一個元素。
當咱們調用到最後一個元素,再次調用next()
函數,會拋這個異常java.util.NoSuchElementException
。代碼示例:
>>> val list = listOf(1,2,3) >>> val iter = list.iterator() >>> iter java.util.AbstractList$Itr@3abfe845 >>> iter.hasNext() true >>> iter.next() 1 >>> iter.hasNext() true >>> iter.next() 2 >>> iter.hasNext() true >>> iter.next() 3 >>> iter.hasNext() false >>> iter.next() java.util.NoSuchElementException at java.util.AbstractList$Itr.next(AbstractList.java:364)
咱們能夠看出,這裏的Iterator的實現是在AbstractList
中的內部類IteratorImpl
:
private open inner class IteratorImpl : Iterator<E> { protected var index = 0 override fun hasNext(): Boolean = index < size override fun next(): E { if (!hasNext()) throw NoSuchElementException() return get(index++) } }
經過這個實現源碼,咱們能夠更加清楚地明白Iterator的工做原理。
其中,NoSuchElementException()
這個類是java.util.NoSuchElementException
的類型別名:
@kotlin.SinceKotlin public typealias NoSuchElementException = java.util.NoSuchElementException
forEach
遍歷List元素這個forEach
函數定義以下:
@kotlin.internal.HidesMembers public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit { for (element in this) action(element) }
它是package kotlin.collections
包下面的Iterable的擴展內聯函數。它的入參是一個函數類型:
action: (T) -> Unit
關於函數式編程,咱們將在後面章節中學習。
這裏的forEach
是一個語法糖。實際上forEach
在遍歷List對象的時候,仍然使用的是iterator迭代器來進行循環遍歷的。
>>> val list = listOf(1,2,3) >>> list [1, 2, 3] >>> list.forEach{ ... println(it) ... } 1 2 3
當參數只有一個函數的時候,括號能夠省略不寫。
也就是說,這裏面的forEach函數調用的寫法,實際上跟下面的寫法等價:
list.forEach({ println(it) })
咱們甚至還能夠直接這樣寫:
>>> list.forEach(::println)
其中,::
是函數引用符。
add
remove
set
clear
這兩個添加、刪除操做函數是MutableList裏面的。跟Java中的集合類操做相似。
建立一個可變集合:
>>> val mutableList = mutableListOf(1,2,3) >>> mutableList [1, 2, 3]
向集合中添加一個元素:
>>> mutableList.add(4) true >>> mutableList [1, 2, 3, 4]
在下標爲0的位置添加元素0 :
>>> mutableList.add(0,0) >>> mutableList [0, 1, 2, 3, 4]
刪除元素1 :
>>> mutableList.remove(1) true >>> mutableList [0, 2, 3, 4] >>> mutableList.remove(1) false
刪除下標爲1的元素:
>>> mutableList.removeAt(1) 2 >>> mutableList [0, 3, 4]
刪除子集合:
>>> mutableList.removeAll(listOf(3,4)) true >>> mutableList [0]
添加子集合:
>>> mutableList.addAll(listOf(1,2,3)) true >>> mutableList [1, 2, 3]
更新設置下標0的元素值爲100:
>>> mutableList.set(0,100) 0 >>> mutableList [100]
清空集合:
>>> mutableList.clear() >>> mutableList []
把可變集合轉爲不可變集合:
>>> mutableList.toList() [1, 2, 3]
retainAll
取兩個集合交集:
>>> val mlist1 = mutableListOf(1,2,3,4,5,6) >>> val mlist2 = mutableListOf(3,4,5,6,7,8,9) >>> mlist1.retainAll(mlist2) true >>> mlist1 [3, 4, 5, 6]
contains(element: T): Boolean
判斷集合中是否有指定元素,有就返回true,不然返回false 。
代碼示例:
>>> val list = listOf(1,2,3,4,5,6,7) >>> list.contains(1) true
elementAt(index: Int): T
查找下標對應的元素,若是下標越界會拋IndexOutOfBoundsException。
代碼示例:
>>> val list = listOf(1,2,3,4,5,6,7) >>> list.elementAt(6) 7 >>> list.elementAt(7) java.lang.ArrayIndexOutOfBoundsException: 7 at java.util.Arrays$ArrayList.get(Arrays.java:3841)
另外,針對越界的處理,還有下面兩個函數:
elementAtOrElse(index: Int, defaultValue: (Int) -> T): T
: 查找下標對應元素,若是越界會根據方法返回默認值。
>>> list.elementAtOrElse(7,{0}) 0 >>> list.elementAtOrElse(7,{10}) 10
elementAtOrNull(index: Int): T?
: 查找下標對應元素,若是越界就返回null
>>> list.elementAtOrNull(7) null
first()
返回集合第1個元素,若是是空集,拋出異常NoSuchElementException。
>>> val list = listOf(1,2,3) >>> list.first() 1 >>> val emptyList = listOf<Int>() >>> emptyList.first() java.util.NoSuchElementException: List is empty. at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:178)
對應的有針對異常處理的函數firstOrNull(): T?
:
>>> emptyList.firstOrNull() null
first(predicate: (T) -> Boolean): T
返回符合條件的第一個元素,沒有則拋異常NoSuchElementException 。
>>> val list = listOf(1,2,3) >>> list.first({it%2==0}) 2 >>> list.first({it>100}) java.util.NoSuchElementException: Collection contains no element matching the predicate.
對應的有針對異常處理的函數firstOrNull(predicate: (T) -> Boolean): T?
,返回符合條件的第一個元素,沒有就返回null :
>>> list.firstOrNull({it>100}) null
indexOf(element: T): Int
返回指定下標的元素,沒有就返回-1
>>> val list = listOf("a","b","c") >>> list.indexOf("c") 2 >>> list.indexOf("x") -1
indexOfFirst(predicate: (T) -> Boolean): Int
返回第一個符合條件的元素下標,沒有就返回-1 。
>>> val list = listOf("abc","xyz","xjk","pqk") >>> list.indexOfFirst({it.contains("x")}) 1 >>> list.indexOfFirst({it.contains("k")}) 2 >>> list.indexOfFirst({it.contains("e")}) -1
indexOfLast(predicate: (T) -> Boolean): Int
返回最後一個符合條件的元素下標,沒有就返回-1 。
>>> val list = listOf("abc","xyz","xjk","pqk") >>> list.indexOfLast({it.contains("x")}) 2 >>> list.indexOfLast({it.contains("k")}) 3 >>> list.indexOfLast({it.contains("e")}) -1
last()
返回集合最後一個元素,空集則拋出異常NoSuchElementException。
>>> val list = listOf(1,2,3,4,7,5,6,7,8) >>> list.last() 8 >>> val emptyList = listOf<Int>() >>> emptyList.last() java.util.NoSuchElementException: List is empty. at kotlin.collections.CollectionsKt___CollectionsKt.last(_Collections.kt:340)
last(predicate: (T) -> Boolean): T
返回符合條件的最後一個元素,沒有就拋NoSuchElementException
>>> val list = listOf(1,2,3,4,7,5,6,7,8) >>> list.last({it==7}) 7 >>> list.last({it>10}) java.util.NoSuchElementException: List contains no element matching the predicate.
對應的針對越界處理的lastOrNull
函數:返回符合條件的最後一個元素,沒有則返回null :
>>> list.lastOrNull({it>10}) null
lastIndexOf(element: T): Int
返回符合條件的最後一個元素,沒有就返回-1
>>> val list = listOf("abc","dfg","jkl","abc","bbc","wer") >>> list.lastIndexOf("abc") 3
single(): T
該集合若是隻有1個元素,則返回該元素。不然,拋異常。
>>> val list = listOf(1) >>> list.single() 1 >>> val list = listOf(1,2) >>> list.single() java.lang.IllegalArgumentException: List has more than one element. at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:471) >>> val list = listOf<Int>() >>> list.single() java.util.NoSuchElementException: List is empty. at kotlin.collections.CollectionsKt___CollectionsKt.single(_Collections.kt:469)
single(predicate: (T) -> Boolean): T
返回符合條件的單個元素,若有沒有符合的拋異常NoSuchElementException,或超過一個的拋異常IllegalArgumentException。
>>> val list = listOf(1,2,3,4,7,5,6,7,8) >>> list.single({it==1}) 1 >>> list.single({it==7}) java.lang.IllegalArgumentException: Collection contains more than one matching element. >>> list.single({it==10}) java.util.NoSuchElementException: Collection contains no element matching the predicate.
對應的針對異常處理的函數singleOrNull
: 返回符合條件的單個元素,若有沒有符合或超過一個,返回null
>>> list.singleOrNull({it==7}) null >>> list.singleOrNull({it==10}) null
any
all
none
count
reduce
fold
max
min
sum
函數算子(operator)any()
判斷集合至少有一個元素這個函數定義以下:
public fun <T> Iterable<T>.any(): Boolean { for (element in this) return true return false }
若是該集合至少有一個元素,返回true
,不然返回false
。
代碼示例:
>>> val emptyList = listOf<Int>() >>> emptyList.any() false >>> val list1 = listOf(1) >>> list1.any() true
any(predicate: (T) -> Boolean)
判斷集合中是否有知足條件的元素這個函數定義以下:
public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean { for (element in this) if (predicate(element)) return true return false }
若是該集合中至少有一個元素匹配謂詞函數參數predicate: (T) -> Boolean
,返回true,不然返回false。
代碼示例:
>>> val list = listOf(1, 2, 3) >>> list.any() // 至少有1個元素 true >>> list.any({it%2==0}) // 元素2知足{it%2==0} true >>> list.any({it>4}) // 沒有元素知足{it>4} false
all(predicate: (T) -> Boolean)
判斷集合中的元素是否都知足條件函數定義:
public inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean { for (element in this) if (!predicate(element)) return false return true }
當且僅當該集合中全部元素都知足條件時,返回true
;不然都返回false
。
代碼示例:
>>> val list = listOf(0,2,4,6,8) >>> list.all({it%2==0}) true >>> list.all({it>2}) false
none()
判斷集合無元素函數定義:
public fun <T> Iterable<T>.none(): Boolean { for (element in this) return false return true }
若是該集合沒有任何元素,返回true
,不然返回false
。
代碼示例:
>>> val list = listOf<Int>() >>> list.none() true
none(predicate: (T) -> Boolean)
判斷集合中全部元素都不知足條件函數定義:
public inline fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean { for (element in this) if (predicate(element)) return false return true }
當且僅當集合中全部元素都不知足條件時返回true
,不然返回false
。
代碼示例:
>>> val list = listOf(0,2,4,6,8) >>> list.none({it%2==1}) true >>> list.none({it>0}) false
count()
計算集合中元素的個數函數定義:
public fun <T> Iterable<T>.count(): Int { var count = 0 for (element in this) count++ return count }
代碼示例:
>>> val list = listOf(0,2,4,6,8,9) >>> list.count() 6
count(predicate: (T) -> Boolean)
計算集合中知足條件的元素的個數函數定義:
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int { var count = 0 for (element in this) if (predicate(element)) count++ return count }
代碼示例:
>>> val list = listOf(0,2,4,6,8,9) >>> list.count() 6 >>> list.count({it%2==0}) 5
reduce
從 第一項到最後一項進行累計運算函數定義:
public inline fun <S, T: S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S { val iterator = this.iterator() if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.") var accumulator: S = iterator.next() while (iterator.hasNext()) { accumulator = operation(accumulator, iterator.next()) } return accumulator }
首先把第一個元素賦值給累加子accumulator
,而後逐次向後取元素累加,新值繼續賦值給累加子accumulator = operation(accumulator, iterator.next())
,以此類推。最後返回累加子的值。
代碼示例:
>>> val list = listOf(1,2,3,4,5,6,7,8,9) >>> list.reduce({sum, next->sum+next}) 45 >>> list.reduce({sum, next->sum*next}) 362880 >>> val list = listOf("a","b","c") >>> list.reduce({total, s->total+s}) abc
reduceRight
從最後一項到第一項進行累計運算函數定義:
public inline fun <S, T: S> List<T>.reduceRight(operation: (T, acc: S) -> S): S { val iterator = listIterator(size) if (!iterator.hasPrevious()) throw UnsupportedOperationException("Empty list can't be reduced.") var accumulator: S = iterator.previous() while (iterator.hasPrevious()) { accumulator = operation(iterator.previous(), accumulator) } return accumulator }
從函數的定義accumulator = operation(iterator.previous(), accumulator)
, 咱們能夠看出,從右邊累計運算的累加子是放在後面的。
代碼示例:
>>> val list = listOf("a","b","c") >>> list.reduceRight({total, s -> s+total}) cba
若是咱們位置放錯了,會輸出下面的結果:
>>> list.reduceRight({total, s -> total+s}) abc
fold(initial: R, operation: (acc: R, T) -> R): R
帶初始值的reduce函數定義:
public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R { var accumulator = initial for (element in this) accumulator = operation(accumulator, element) return accumulator }
從函數的定義,咱們能夠看出,fold函數給累加子賦了初始值initial
。
代碼示例:
>>> val list=listOf(1,2,3,4) >>> list.fold(100,{total, next -> next + total}) 110
foldRight
和reduceRight
相似,有初始值。
函數定義:
public inline fun <T, R> List<T>.foldRight(initial: R, operation: (T, acc: R) -> R): R { var accumulator = initial if (!isEmpty()) { val iterator = listIterator(size) while (iterator.hasPrevious()) { accumulator = operation(iterator.previous(), accumulator) } } return accumulator }
代碼示例:
>>> val list = listOf("a","b","c") >>> list.foldRight("xyz",{s, pre -> pre + s}) xyzcba
forEach(action: (T) -> Unit): Unit
循環遍歷元素,元素是it咱們在前文已經講述,參看5.3.4。
再寫個代碼示例:
>>> val list = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) >>> list.forEach { value -> if (value > 7) println(value) } 8 9
forEachIndexed
帶index(下標) 的元素遍歷函數定義:
public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit { var index = 0 for (item in this) action(index++, item) }
代碼示例:
>>> val list = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) >>> list.forEachIndexed { index, value -> if (value > 8) println("value of index $index is $value, greater than 8") } value of index 9 is 9, greater than 8
max
、min
查詢最大、最小的元素,空集則返回nullmax
函數定義:
public fun <T : Comparable<T>> Iterable<T>.max(): T? { val iterator = iterator() if (!iterator.hasNext()) return null var max = iterator.next() while (iterator.hasNext()) { val e = iterator.next() if (max < e) max = e } return max }
返回集合中最大的元素。
代碼示例:
>>> val list = listOf(1,2,3) >>> list.max() 3 >>> val list = listOf("a","b","c") >>> list.max() c
min
函數定義:
public fun <T : Comparable<T>> Iterable<T>.min(): T? { val iterator = iterator() if (!iterator.hasNext()) return null var min = iterator.next() while (iterator.hasNext()) { val e = iterator.next() if (min > e) min = e } return min }
返回集合中的最小元素。
代碼示例:
>>> val list = listOf(1,2,3) >>> list.min() 1 >>> val list = listOf("a","b","c") >>> list.min() a
在Kotlin中,字符串的大小比較比較有意思的,咱們直接經過代碼示例來學習一下:
>>> "c" > "a" true >>> "abd" > "abc" true >>> "abd" > "abcd" true >>> "abd" > "abcdefg" true
咱們能夠看出,字符串的大小比較是按照對應的下標的字符進行比較的。
另外,布爾值的比較是true
大於false
:
>>> true > false true
maxBy(selector: (T) -> R): T?
、 minBy(selector: (T) -> R): T?
獲取函數映射結果的最大值、最小值對應的那個元素的值,若是沒有則返回null函數定義:
public inline fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? { val iterator = iterator() if (!iterator.hasNext()) return null var maxElem = iterator.next() var maxValue = selector(maxElem) while (iterator.hasNext()) { val e = iterator.next() val v = selector(e) if (maxValue < v) { maxElem = e maxValue = v } } return maxElem }
也就是說,不直接比較集合元素的大小,而是以集合元素爲入參的函數selector: (T) -> R
返回值來比較大小,最後返回此元素的值(注意,不是對應的selector
函數的返回值)。有點像數學裏的求函數最值問題:
給定函數 y = f(x)
, 求 max f(x)
的x
的值。
代碼示例:
>>> val list = listOf(100,-500,300,200) >>> list.maxBy({it}) 300 >>> list.maxBy({it*(1-it)}) 100 >>> list.maxBy({it*it}) -500
對應的 minBy
是獲取函數映射後返回結果的最小值所對應那個元素的值,若是沒有則返回null。
代碼示例:
>>> val list = listOf(100,-500,300,200) >>> list.minBy({it}) -500 >>> list.minBy({it*(1-it)}) -500 >>> list.minBy({it*it}) 100
sumBy(selector: (T) -> Int): Int
獲取函數映射值的總和函數定義:
public inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int { var sum: Int = 0 for (element in this) { sum += selector(element) } return sum }
能夠看出,這個sumBy
函數算子,累加器sum
初始值爲0,返回值是Int
。它的入參selector
是一個函數類型(T) -> Int
,也就是說這個selector也是返回Int類型的函數。
代碼示例:
>>> val list = listOf(1,2,3,4) >>> list.sumBy({it}) 10 >>> list.sumBy({it*it}) 30
類型錯誤反例:
>>> val list = listOf("a","b","c") >>> list.sumBy({it}) error: type inference failed: inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int cannot be applied to receiver: List<String> arguments: ((String) -> String) list.sumBy({it}) ^ error: type mismatch: inferred type is (String) -> String but (String) -> Int was expected list.sumBy({it}) ^
take(n: Int): List<T>
挑出該集合前n個元素的子集合函數定義:
public fun <T> Iterable<T>.take(n: Int): List<T> { require(n >= 0) { "Requested element count $n is less than zero." } if (n == 0) return emptyList() if (this is Collection<T>) { if (n >= size) return toList() if (n == 1) return listOf(first()) } var count = 0 val list = ArrayList<T>(n) for (item in this) { if (count++ == n) break list.add(item) } return list.optimizeReadOnlyList() }
若是n等於0,返回空集;若是n大於集合size
,返回該集合。
代碼示例:
>>> val list = listOf("a","b","c") >>> list [a, b, c] >>> list.take(2) [a, b] >>> list.take(10) [a, b, c] >>> list.take(0) []
takeWhile(predicate: (T) -> Boolean): List<T>
挑出知足條件的元素的子集合函數定義:
public inline fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T> { val list = ArrayList<T>() for (item in this) { if (!predicate(item)) break list.add(item) } return list }
從第一個元素開始,判斷是否知足predicate
爲true,若是知足條件的元素就丟到返回ArrayList
中。只要遇到任何一個元素不知足條件,就結束循環,返回list 。
代碼示例:
>>> val list = listOf(1,2,4,6,8,9) >>> list.takeWhile({it%2==0}) [] >>> list.takeWhile({it%2==1}) [1] >>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.takeWhile({it%2==0}) [2, 4, 6, 8]
takeLast
挑出後n個元素的子集合函數定義:
public fun <T> List<T>.takeLast(n: Int): List<T> { require(n >= 0) { "Requested element count $n is less than zero." } if (n == 0) return emptyList() val size = size if (n >= size) return toList() if (n == 1) return listOf(last()) val list = ArrayList<T>(n) if (this is RandomAccess) { for (index in size - n .. size - 1) list.add(this[index]) } else { for (item in listIterator(n)) list.add(item) } return list }
從集合倒數n個元素起,取出到最後一個元素的子集合。若是傳入0,返回空集。若是傳入n大於集合size,返回整個集合。若是傳入負數,直接拋出IllegalArgumentException。
代碼示例:
>>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.takeLast(0) [] >>> list.takeLast(3) [11, 12, 16] >>> list.takeLast(100) [2, 4, 6, 8, 9, 11, 12, 16] >>> list.takeLast(-1) java.lang.IllegalArgumentException: Requested element count -1 is less than zero. at kotlin.collections.CollectionsKt___CollectionsKt.takeLast(_Collections.kt:734)
takeLastWhile(predicate: (T) -> Boolean)
從最後開始挑出知足條件元素的子集合函數定義:
public inline fun <T> List<T>.takeLastWhile(predicate: (T) -> Boolean): List<T> { if (isEmpty()) return emptyList() val iterator = listIterator(size) while (iterator.hasPrevious()) { if (!predicate(iterator.previous())) { iterator.next() val expectedSize = size - iterator.nextIndex() if (expectedSize == 0) return emptyList() return ArrayList<T>(expectedSize).apply { while (iterator.hasNext()) add(iterator.next()) } } } return toList() }
反方向取知足條件的元素,遇到不知足的元素,直接終止循環,並返回子集合。
代碼示例:
>>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.takeLastWhile({it%2==0}) [12, 16]
drop(n: Int)
去除前n個元素返回剩下的元素的子集合函數定義:
public fun <T> Iterable<T>.drop(n: Int): List<T> { require(n >= 0) { "Requested element count $n is less than zero." } if (n == 0) return toList() val list: ArrayList<T> if (this is Collection<*>) { val resultSize = size - n if (resultSize <= 0) return emptyList() if (resultSize == 1) return listOf(last()) list = ArrayList<T>(resultSize) if (this is List<T>) { if (this is RandomAccess) { for (index in n..size - 1) list.add(this[index]) } else { for (item in listIterator(n)) list.add(item) } return list } } else { list = ArrayList<T>() } var count = 0 for (item in this) { if (count++ >= n) list.add(item) } return list.optimizeReadOnlyList() }
代碼示例:
>>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.drop(5) [11, 12, 16] >>> list.drop(100) [] >>> list.drop(0) [2, 4, 6, 8, 9, 11, 12, 16] >>> list.drop(-1) java.lang.IllegalArgumentException: Requested element count -1 is less than zero. at kotlin.collections.CollectionsKt___CollectionsKt.drop(_Collections.kt:538)
dropWhile(predicate: (T) -> Boolean)
去除知足條件的元素返回剩下的元素的子集合函數定義:
public inline fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T> { var yielding = false val list = ArrayList<T>() for (item in this) if (yielding) list.add(item) else if (!predicate(item)) { list.add(item) yielding = true } return list }
去除知足條件的元素,當遇到一個不知足條件的元素時,停止操做,返回剩下的元素子集合。
代碼示例:
>>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.dropWhile({it%2==0}) [9, 11, 12, 16]
dropLast(n: Int)
從最後去除n個元素函數定義:
public fun <T> List<T>.dropLast(n: Int): List<T> { require(n >= 0) { "Requested element count $n is less than zero." } return take((size - n).coerceAtLeast(0)) }
代碼示例:
>>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.dropLast(3) [2, 4, 6, 8, 9] >>> list.dropLast(100) [] >>> list.dropLast(0) [2, 4, 6, 8, 9, 11, 12, 16] >>> list.dropLast(-1) java.lang.IllegalArgumentException: Requested element count -1 is less than zero. at kotlin.collections.CollectionsKt___CollectionsKt.dropLast(_Collections.kt:573)
dropLastWhile(predicate: (T) -> Boolean)
從最後知足條件的元素函數定義:
public inline fun <T> List<T>.dropLastWhile(predicate: (T) -> Boolean): List<T> { if (!isEmpty()) { val iterator = listIterator(size) while (iterator.hasPrevious()) { if (!predicate(iterator.previous())) { return take(iterator.nextIndex() + 1) } } } return emptyList() }
代碼示例:
>>> val list = listOf(2,4,6,8,9,11,12,16) >>> list.dropLastWhile({it%2==0}) [2, 4, 6, 8, 9, 11]
slice(indices: IntRange)
取開始下標至結束下標元素子集合函數定義:
public fun <T> List<T>.slice(indices: IntRange): List<T> { if (indices.isEmpty()) return listOf() return this.subList(indices.start, indices.endInclusive + 1).toList() }
代碼示例:
val list = listOf(2,4,6,8,9,11,12,16) >>> list [2, 4, 6, 8, 9, 11, 12, 16] >>> list.slice(1..3) [4, 6, 8] >>> list.slice(2..7) [6, 8, 9, 11, 12, 16] >>> list [2, 4, 6, 8, 9, 11, 12, 16] >>> list.slice(1..3) [4, 6, 8] >>> list.slice(2..7) [6, 8, 9, 11, 12, 16]
slice(indices: Iterable<Int>)
返回指定下標的元素子集合函數定義:
public fun <T> List<T>.slice(indices: Iterable<Int>): List<T> { val size = indices.collectionSizeOrDefault(10) if (size == 0) return emptyList() val list = ArrayList<T>(size) for (index in indices) { list.add(get(index)) } return list }
這個函數從簽名上看,不是那麼簡單直接。從函數的定義看,這裏的indices是當作原來集合的下標來使用的。
代碼示例:
>>> list [2, 4, 6, 8, 9, 11, 12, 16] >>> list.slice(listOf(2,4,6)) [6, 9, 12]
咱們能夠看出,這裏是取出下標爲2,4,6的元素。而不是直觀理解上的,去掉元素2,4,6。
filterTo(destination: C, predicate: (T) -> Boolean)
過濾出知足條件的元素並賦值給destination函數定義:
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C { for (element in this) if (predicate(element)) destination.add(element) return destination }
把知足過濾條件的元素組成的子集合賦值給入參destination。
代碼示例:
>>> val list = listOf(1,2,3,4,5,6,7) >>> val dest = mutableListOf<Int>() >>> list.filterTo(dest,{it>3}) [4, 5, 6, 7] >>> dest [4, 5, 6, 7]
filter(predicate: (T) -> Boolean)
過濾出知足條件的元素組成的子集合函數定義:
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> { return filterTo(ArrayList<T>(), predicate) }
相對於filterTo函數,filter函數更加簡單易用。從源碼咱們能夠看出,filter函數直接調用的filterTo(ArrayList<T>(), predicate)
, 其中入參destination被直接默認賦值爲ArrayList<T>()
。
代碼示例:
>>> val list = listOf(1,2,3,4,5,6,7) >>> list.filter({it>3}) [4, 5, 6, 7]
另外,還有下面經常使用的過濾函數:
filterNot(predicate: (T) -> Boolean)
, 用來過濾全部不知足條件的元素 ;filterNotNull()
過濾掉null
元素。
map(transform: (T) -> R): List<R>
將集合中的元素經過轉換函數transform
映射後的結果,存到一個集合中返回。
>>> val list = listOf(1,2,3,4,5,6,7) >>> list.map({it}) [1, 2, 3, 4, 5, 6, 7] >>> list.map({it*it}) [1, 4, 9, 16, 25, 36, 49] >>> list.map({it+10}) [11, 12, 13, 14, 15, 16, 17]
這個函數內部調用的是
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> { return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform) }
這裏的mapTo函數定義以下:
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C { for (item in this) destination.add(transform(item)) return destination }
咱們能夠看出,這個map實現的原理是循環遍歷原集合中的元素,並把經過transform映射後的結果放到一個新的destination集合中,並返回destination。
mapIndexed(transform: (kotlin.Int, T) -> R)
轉換函數transform
中帶有下標參數。也就是說咱們能夠同時使用下標和元素的值來進行轉換。 其中,第一個參數是Int類型的下標。
代碼示例:
>>> val list = listOf(1,2,3,4,5,6,7) >>> list.mapIndexed({index,it -> index*it}) [0, 2, 6, 12, 20, 30, 42]
mapNotNull(transform: (T) -> R?)
遍歷集合每一個元素,獲得經過函數算子transform映射以後的值,剔除掉這些值中的null,返回一個無null元素的集合。
代碼示例:
>>> val list = listOf("a","b",null,"x",null,"z") >>> list.mapNotNull({it}) [a, b, x, z]
這個函數內部實現是調用的mapNotNullTo
函數:
public inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapNotNullTo(destination: C, transform: (T) -> R?): C { forEach { element -> transform(element)?.let { destination.add(it) } } return destination }
flatMap(transform: (T) -> Iterable<R>): List<R>
在原始集合的每一個元素上調用transform
轉換函數,獲得的映射結果組成的單個列表。爲了更簡單的理解這個函數,咱們跟map(transform: (T) -> R): List<R>
對比下。
首先看函數的各自的實現:
map:
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> { return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform) } public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C { for (item in this) destination.add(transform(item)) return destination }
flatMap:
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> { return flatMapTo(ArrayList<R>(), transform) } public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C { for (element in this) { val list = transform(element) destination.addAll(list) } return destination }
咱們能夠看出,這兩個函數主要區別在transform函數返回上。
代碼示例
>>> val list = listOf("a","b","c") >>> list.map({it->listOf(it+1,it+2,it+3)}) [[a1, a2, a3], [b1, b2, b3], [c1, c2, c3]] >>> list.flatMap({it->listOf(it+1,it+2,it+3)}) [a1, a2, a3, b1, b2, b3, c1, c2, c3]
從代碼運行結果咱們能夠看出,使用 map 是把list中的每個元素都映射成一個List-n
,而後以這些List-n
爲元素,組成一個大的嵌套的List
返回。而使用flatMap則是把list中的第一個元素映射成一個List1,而後把第二個元素映射成的List2跟List1合併:List1.addAll(List2)
,以此類推。最終返回一個「扁平的」(flat)List。
其實,這個flatMap的過程是 map + flatten
兩個操做的組合。這個flatten函數定義以下:
public fun <T> Iterable<Iterable<T>>.flatten(): List<T> { val result = ArrayList<T>() for (element in this) { result.addAll(element) } return result }
代碼示例:
>>> val list = listOf("a","b","c") >>> list.map({it->listOf(it+1,it+2,it+3)}) [[a1, a2, a3], [b1, b2, b3], [c1, c2, c3]] >>> list.map({it->listOf(it+1,it+2,it+3)}).flatten() [a1, a2, a3, b1, b2, b3, c1, c2, c3]
groupBy(keySelector: (T) -> K): Map<K, List<T>>
將集合中的元素按照條件選擇器keySelector
(是一個函數)分組,並返回Map。
代碼示例:
>>> val words = listOf("a", "abc", "ab", "def", "abcd") >>> val lengthGroup = words.groupBy { it.length } >>> lengthGroup {1=[a], 3=[abc, def], 2=[ab], 4=[abcd]}
groupBy(keySelector: (T) -> K, valueTransform: (T) -> V)
分組函數還有一個是groupBy(keySelector: (T) -> K, valueTransform: (T) -> V)
,根據條件選擇器keySelector和轉換函數valueTransform分組。
代碼示例
>>> val programmer = listOf("K&R" to "C", "Bjar" to "C++", "Linus" to "C", "James" to "Java") >>> programmer [(K&R, C), (Bjar, C++), (Linus, C), (James, Java)] >>> programmer.groupBy({it.second}, {it.first}) {C=[K&R, Linus], C++=[Bjar], Java=[James]}
這裏涉及到一個 二元組Pair 類,該類是Kotlin提供的用來處理二元數據組的。 能夠理解成Map中的一個鍵值對,好比Pair(「key」,」value」) 等價於 「key」 to 「value」。
咱們再經過下面的代碼示例,來看一下這兩個分組的區別:
>>> val words = listOf("a", "abc", "ab", "def", "abcd") >>> words.groupBy( { it.length }) {1=[a], 3=[abc, def], 2=[ab], 4=[abcd]} >>> words.groupBy( { it.length },{it.contains("b")}) {1=[false], 3=[true, false], 2=[true], 4=[true]}
咱們能夠看出,後者是在前者的基礎上又映射了一次{it.contains("b")}
,把第2次映射的結果放到返回的Map中了。
groupingBy(crossinline keySelector: (T) -> K): Grouping<T, K>
另外,咱們還可使用groupingBy(crossinline keySelector: (T) -> K): Grouping<T, K>
函數來建立一個Grouping
,而後調用計數函數eachCount
統計分組:
代碼示例
>>> val words = "one two three four five six seven eight nine ten".split(' ') >>> words.groupingBy({it.first()}).eachCount() {o=1, t=3, f=2, s=2, e=1, n=1}
上面的例子是統計words列表的元素單詞中首字母出現的頻數。
其中,eachCount
函數定義以下:
@SinceKotlin("1.1") @JvmVersion public fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int> = // fold(0) { acc, e -> acc + 1 } optimized for boxing foldTo( destination = mutableMapOf(), initialValueSelector = { _, _ -> kotlin.jvm.internal.Ref.IntRef() }, operation = { _, acc, _ -> acc.apply { element += 1 } }) .mapValuesInPlace { it.value.element }
reversed(): List<T>
倒序排列集合元素。
代碼示例
>>> val list = listOf(1,2,3) >>> list.reversed() [3, 2, 1]
這個函數,Kotlin是直接調用的java.util.Collections.reverse()
方法。其相關代碼以下:
public fun <T> Iterable<T>.reversed(): List<T> { if (this is Collection && size <= 1) return toList() val list = toMutableList() list.reverse() return list } public fun <T> MutableList<T>.reverse(): Unit { java.util.Collections.reverse(this) }
sorted
和sortedDescending
升序排序和降序排序。
代碼示例
>>> val list = listOf(1,3,2) >>> list.sorted() [1, 2, 3] >>> list.sortedDescending() [3, 2, 1]
sortedBy
和sortedByDescending
可變集合MutableList的排序操做。根據函數映射的結果進行升序排序和降序排序。
這兩個函數定義以下:
public inline fun <T, R : Comparable<R>> MutableList<T>.sortBy(crossinline selector: (T) -> R?): Unit { if (size > 1) sortWith(compareBy(selector)) } public inline fun <T, R : Comparable<R>> MutableList<T>.sortByDescending(crossinline selector: (T) -> R?): Unit { if (size > 1) sortWith(compareByDescending(selector)) }
代碼示例
>>> val mlist = mutableListOf("abc","c","bn","opqde","") >>> mlist.sortBy({it.length}) >>> mlist [, c, bn, abc, opqde] >>> mlist.sortByDescending({it.length}) >>> mlist [opqde, abc, bn, c, ]
zip(other: Iterable<R>): List<Pair<T, R>>
兩個集合按照下標配對,組合成的每一個Pair做爲新的List集合中的元素,並返回。
若是兩個集合長度不同,取短的長度。
代碼示例
>>> val list1 = listOf(1,2,3) >>> val list2 = listOf(4,5,6,7) >>> val list3 = listOf("x","y","z") >>> list1.zip(list3) [(1, x), (2, y), (3, z)] >>> list3.zip(list1) [(x, 1), (y, 2), (z, 3)] >>> list2.zip(list3) [(4, x), (5, y), (6, z)] // 取短的長度 >>> list3.zip(list2) [(x, 4), (y, 5), (z, 6)] >>> list1.zip(listOf<Int>()) []
這個zip函數的定義以下:
public infix fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>> { return zip(other) { t1, t2 -> t1 to t2 } }
咱們能夠看出,其內部是調用了zip(other) { t1, t2 -> t1 to t2 }
。這個函數定義以下:
public inline fun <T, R, V> Iterable<T>.zip(other: Iterable<R>, transform: (a: T, b: R) -> V): List<V> { val first = iterator() val second = other.iterator() val list = ArrayList<V>(minOf(collectionSizeOrDefault(10), other.collectionSizeOrDefault(10))) while (first.hasNext() && second.hasNext()) { list.add(transform(first.next(), second.next())) } return list }
依次取兩個集合相同索引的元素,使用提供的轉換函數transform獲得映射以後的值,做爲元素組成一個新的List,並返回該List。列表的長度取兩個集合中最短的。
代碼示例
>>> val list1 = listOf(1,2,3) >>> val list2 = listOf(4,5,6,7) >>> val list3 = listOf("x","y","z") >>> list1.zip(list3, {t1,t2 -> t2+t1}) [x1, y2, z3] >>> list1.zip(list2, {t1,t2 -> t1*t2}) [4, 10, 18]
unzip(): Pair<List<T>, List<R>>
首先這個函數做用在元素是Pair的集合類上。依次取各個Pair元素的first, second值,分別放到List<T>、List<R>中,而後返回一個first爲List<T>,second爲List<R>的大的Pair。
函數定義
public fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>> { val expectedSize = collectionSizeOrDefault(10) val listT = ArrayList<T>(expectedSize) val listR = ArrayList<R>(expectedSize) for (pair in this) { listT.add(pair.first) listR.add(pair.second) } return listT to listR }
看到這裏,仍然有點抽象,咱們直接看代碼示例:
>>> val listPair = listOf(Pair(1,2),Pair(3,4),Pair(5,6)) >>> listPair [(1, 2), (3, 4), (5, 6)] >>> listPair.unzip() ([1, 3, 5], [2, 4, 6])
partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>>
根據判斷條件是否成立,將集合拆分紅兩個子集合組成的 Pair。咱們能夠直接看函數的定義來更加清晰的理解這個函數的功能:
public inline fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>> { val first = ArrayList<T>() val second = ArrayList<T>() for (element in this) { if (predicate(element)) { first.add(element) } else { second.add(element) } } return Pair(first, second) }
咱們能夠看出,這是一個內聯函數。
代碼示例
>>> val list = listOf(1,2,3,4,5,6,7,8,9) >>> list [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list.partition({it>5}) ([6, 7, 8, 9], [1, 2, 3, 4, 5])
plus(elements: Iterable<T>): List<T>
合併兩個List。
函數定義
public operator fun <T> Iterable<T>.plus(elements: Iterable<T>): List<T> { if (this is Collection) return this.plus(elements) val result = ArrayList<T>() result.addAll(this) result.addAll(elements) return result }
咱們能夠看出,這是一個操做符函數。能夠用」+」替代 。
代碼示例
>>> val list1 = listOf(1,2,3) >>> val list2 = listOf(4,5) >>> list1.plus(list2) [1, 2, 3, 4, 5] >>> list1+list2 [1, 2, 3, 4, 5]
關於plus函數還有如下的重載函數:
plus(element: T): List<T> plus(elements: Array<out T>): List<T> plus(elements: Sequence<T>): List<T>
等。
plusElement(element: T): List<T>
在集合中添加一個元素。
函數定義
@kotlin.internal.InlineOnly public inline fun <T> Iterable<T>.plusElement(element: T): List<T> { return plus(element) }
咱們能夠看出,這個函數內部是直接調用的plus(element: T): List<T>
。
代碼示例
>>> list1 + 10 [1, 2, 3, 10] >>> list1.plusElement(10) [1, 2, 3, 10] >>> list1.plus(10) [1, 2, 3, 10]
相似的,Kotlin中的Set也分爲:不可變Set和支持增長和刪除的可變MutableSet。
不可變Set一樣是繼承了Collection。MutableSet接口繼承於Set, MutableCollection,同時對Set進行擴展,添加了對元素添加和刪除等操做。
Set的類圖結構以下:
萬物生於無。咱們先來看下Kotlin中的空集:
internal object EmptySet : Set<Nothing>, Serializable { private const val serialVersionUID: Long = 3406603774387020532 override fun equals(other: Any?): Boolean = other is Set<*> && other.isEmpty() override fun hashCode(): Int = 0 override fun toString(): String = "[]" override val size: Int get() = 0 override fun isEmpty(): Boolean = true override fun contains(element: Nothing): Boolean = false override fun containsAll(elements: Collection<Nothing>): Boolean = elements.isEmpty() override fun iterator(): Iterator<Nothing> = EmptyIterator private fun readResolve(): Any = EmptySet }
空集繼承了Serializable,代表是可被序列化的。它的size是0, isEmpty()返回true,hashCode()也是0。
下面是建立一個空集的代碼示例:
>>> val emptySet = emptySet<Int>() >>> emptySet [] >>> emptySet.size 0 >>> emptySet.isEmpty() true >>> emptySet.hashCode() 0
setOf
首先,Set中的元素是不可重複的(任意兩個元素 x, y 都不相等)。這裏的元素 x, y 不相等的意思是:
x.hashCode() != y.hashCode() !x.equals(y)
上面兩個表達式值都爲true 。
代碼示例
>>> val list = listOf(1,1,2,3,3) >>> list [1, 1, 2, 3, 3] >>> val set = setOf(1,1,2,3,3) >>> set [1, 2, 3]
Kotlin跟Java同樣的,判斷兩個對象的是否重複標準是hashCode()和equals()兩個參考值,也就是說只有兩個對象的hashCode值同樣與equals()爲真時,才認爲是相同的對象。因此自定義的類必需要要重寫hashCode()和equals()兩個函數。做爲Java程序員,這裏通常都會注意到。
建立多個元素的Set使用的函數是
setOf(vararg elements: T): Set<T> = if (elements.size > 0) elements.toSet() else emptySet()
這個toSet()函數是Array類的擴展函數,定義以下
public fun <T> Array<out T>.toSet(): Set<T> { return when (size) { 0 -> emptySet() 1 -> setOf(this[0]) else -> toCollection(LinkedHashSet<T>(mapCapacity(size))) } }
咱們能夠看出,setOf函數背後實際上用的是LinkedHashSet構造函數。關於建立Set的初始容量的算法是:
@PublishedApi internal fun mapCapacity(expectedSize: Int): Int { if (expectedSize < 3) { return expectedSize + 1 } if (expectedSize < INT_MAX_POWER_OF_TWO) { return expectedSize + expectedSize / 3 } return Int.MAX_VALUE // 2147483647, any large value }
也就是說,當元素個數n小於3,初始容量爲n+1;
當元素個數n小於2147483647 / 2 + 1
, 初始容量爲 n + n/3
;
不然,初始容量爲2147483647
。
若是咱們想對一個List去重,能夠直接使用下面的方式
>>> list.toSet() [1, 2, 3]
上文咱們使用emptySet<Int>()
來建立空集,咱們也可使用setOf()來建立空集:
>>> val s = setOf<Int>() >>> s []
建立1個元素的Set:
>>> val s = setOf<Int>(1) >>> s [1]
這個函數調用的是setOf(element: T): Set<T> = java.util.Collections.singleton(element)
, 也是Java的Collections類裏的方法。
mutableSetOf(): MutableSet<T>
建立一個可變Set。
函數定義
@SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun <T> mutableSetOf(): MutableSet<T> = LinkedHashSet()
這個LinkedHashSet()
構造函數背後其實是java.util.LinkedHashSet<E>
, 這就是Kotlin中的類型別名。
包kotlin.collections下面的TypeAliases.kt類中,有一些類型別名的定義以下:
@file:kotlin.jvm.JvmVersion package kotlin.collections @SinceKotlin("1.1") public typealias RandomAccess = java.util.RandomAccess @SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E> @SinceKotlin("1.1") public typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V> @SinceKotlin("1.1") public typealias HashMap<K, V> = java.util.HashMap<K, V> @SinceKotlin("1.1") public typealias LinkedHashSet<E> = java.util.LinkedHashSet<E> @SinceKotlin("1.1") public typealias HashSet<E> = java.util.HashSet<E> // also @SinceKotlin("1.1") internal typealias SortedSet<E> = java.util.SortedSet<E> internal typealias TreeSet<E> = java.util.TreeSet<E>
從這裏,咱們能夠看出,Kotlin中的LinkedHashSet
, HashSet
, SortedSet
, TreeSet
就是直接使用的Java中的對應的集合類。
對應的建立的方法是
hashSetOf linkedSetOf mutableSetOf sortedSetOf
代碼示例以下:
>>> val hs = hashSetOf(1,3,2,7) >>> hs [1, 2, 3, 7] >>> hs::class class java.util.HashSet >>> val ls = linkedSetOf(1,3,2,7) >>> ls [1, 3, 2, 7] >>> ls::class class java.util.LinkedHashSet >>> val ms = mutableSetOf(1,3,2,7) >>> ms [1, 3, 2, 7] >>> ms::class class java.util.LinkedHashSet >>> val ss = sortedSetOf(1,3,2,7) >>> ss [1, 2, 3, 7] >>> ss::class class java.util.TreeSet
咱們知道在Java中,Set接口有兩個主要的實現類HashSet和TreeSet:
HashSet : 該類按照哈希算法來存取集合中的對象,存取速度較快。
TreeSet : 該類實現了SortedSet接口,可以對集合中的對象進行排序。
LinkedHashSet:具備HashSet的查詢速度,且內部使用鏈表維護元素的順序,在對Set元素進行頻繁插入、刪除的場景中使用。
Kotlin並無單獨去實現一套HashSet、TreeSet和LinkedHashSet。若是咱們在實際開發過程當中,須要用到這些Set, 就能夠直接用上面的方法。
plus
minus
Kotlin中針對Set作了一些加減運算的擴展函數, 例如:
operator fun <T> Set<T>.plus(element: T) plusElement(element: T) plus(elements: Iterable<T>) operator fun <T> Set<T>.minus(element: T) minusElement(element: T) minus(elements: Iterable<T>)
代碼示例:
>>> val ms = mutableSetOf(1,3,2,7) >>> ms+10 [1, 3, 2, 7, 10] >>> ms-1 [3, 2, 7] >>> >>> ms + listOf(8,9) [1, 3, 2, 7, 8, 9] >>> ms - listOf(8,9) [1, 3, 2, 7] >>> ms - listOf(1,3) [2, 7]
Map是一種把鍵對象Key和值對象Value映射的集合,它的每個元素都包含一對鍵對象和值對象(K-V Pair)。 Key能夠當作是Value 的索引,做爲key的對象在集合中不可重複(uniq)。
若是咱們從數據結構的本質上來看,其實List就是Key是Int類型下標的特殊的Map。而Set也是Key爲Int,可是Value值不能重複的特殊Map。
Kotlin中的Map與List、Set同樣,Map也分爲只讀Map和可變的MutableMap。
Map沒有繼承於Collection接口。其類圖結構以下:
在接口interface Map<K, out V>
中,K是鍵值的類型,V是對應的映射值的類型。這裏的out V
表示類型爲V或V的子類。這是泛型的相關知識,咱們將在下一章節中介紹。
其中,Entry<out K, out V>
中保存的是Map的鍵值對。
跟Java相比不一樣的是,在Kotlin中的Map區分了只讀的Map和可編輯的Map(MutableMap、HashMap、LinkedHashMap)。
Kotlin沒有本身從新去實現一套集合類,而是在Java的集合類基礎上作了一些擴展。
咱們知道在Java中,根據內部數據結構的不一樣,Map 接口一般有多種實現類。
其中經常使用的有:
HashMap是基於哈希表(hash table)的 Map 接口的實現,以key-value的形式存在。在HashMap中,key-value是一個總體,系統會根據hash算法來來計算key-value的存儲位置,咱們能夠經過key快速地存取value。它容許使用 null 值和 null 鍵。
另外,HashMap中元素的順序,隨着時間的推移會發生變化。
使用紅黑二叉樹(red-black tree)的 Map 接口的實現。
還有繼承了HashMap,並使用鏈表實現的LinkedHashMap。LinkedHashMap保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時,先獲得的記錄是先插入的記錄。簡單說,LinkedHashMap是有序的,它使用鏈表維護內部次序。
咱們在使用Kotlin建立Map的時候,實際上大部分都是調用Java的Map的方法。
下面咱們就來介紹Map的建立以及基本操做函數。
mapOf()
建立一個只讀空Map。
>>> val map1 = mapOf<String, Int>() >>> map1.size 0 >>> map1.isEmpty() true
咱們還能夠用另一個函數建立空Map:
>>> val map2 = emptyMap<String, Int>() >>> map2.size 0 >>> map2.isEmpty() true
空Map都是相等的:
>>> map2==map1 true
這個空Map是隻讀的,其屬性和函數返回都是預約義好的。其代碼以下:
private object EmptyMap : Map<Any?, Nothing>, Serializable { private const val serialVersionUID: Long = 8246714829545688274 override fun equals(other: Any?): Boolean = other is Map<*,*> && other.isEmpty() override fun hashCode(): Int = 0 override fun toString(): String = "{}" override val size: Int get() = 0 override fun isEmpty(): Boolean = true override fun containsKey(key: Any?): Boolean = false override fun containsValue(value: Nothing): Boolean = false override fun get(key: Any?): Nothing? = null override val entries: Set<Map.Entry<Any?, Nothing>> get() = EmptySet override val keys: Set<Any?> get() = EmptySet override val values: Collection<Nothing> get() = EmptyList private fun readResolve(): Any = EmptyMap }
mapOf(pair: Pair<K, V>): Map<K, V>
使用二元組Pair建立一個只讀Map。
>>> val map = mapOf(1 to "x", 2 to "y", 3 to "z") >>> map {1=x, 2=y, 3=z} >>> map.get(1) x >>> map.get(3) z >>> map.size 3 >>> map.entries [1=x, 2=y, 3=z]
這個建立函數內部是調用的LinkedHashMap構造函數,其相關代碼以下:
pairs.toMap(LinkedHashMap(mapCapacity(pairs.size)))
若是咱們想編輯這個Map, 編譯器會直接報錯
>>> map[1]="a" error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch: @InlineOnly public operator inline fun <K, V> MutableMap<Int, String>.set(key: Int, value: String): Unit defined in kotlin.collections @InlineOnly public operator inline fun kotlin.text.StringBuilder /* = java.lang.StringBuilder */.set(index: Int, value: Char): Unit defined in kotlin.text map[1]="a" ^ error: no set method providing array access map[1]="a" ^
由於在不可變(Immutable)Map中,根本就沒有提供set函數。
mutableMapOf()
建立一個空的可變的Map。
>>> val map = mutableMapOf<Int, Any?>() >>> map.isEmpty() true >>> map[1] = "x" >>> map[2] = 1 >>> map {1=x, 2=1}
該函數直接是調用的LinkedHashMap()構造函數。
mutableMapOf(vararg pairs: Pair<K, V>): MutableMap<K, V>
建立一個可編輯的MutableMap對象。
>>> val map = mutableMapOf(1 to "x", 2 to "y", 3 to "z") >>> map {1=x, 2=y, 3=z} >>> map[1]="a" >>> map {1=a, 2=y, 3=z}
另外,若是Map中有重複的key鍵,後面的會直接覆蓋掉前面的:
>>> val map = mutableMapOf(1 to "x", 2 to "y", 1 to "z") >>> map {1=z, 2=y}
後面的1 to "z"
直接把前面的1 to "x"
覆蓋掉了。
hashMapOf(): HashMap<K, V>
建立HashMap對象。Kotlin直接使用的是Java的HashMap。
>>> val map: HashMap<Int, String> = hashMapOf(1 to "x", 2 to "y", 3 to "z") >>> map {1=x, 2=y, 3=z}
linkedMapOf(): LinkedHashMap<K, V>
建立空對象LinkedHashMap。直接使用的是Java中的LinkedHashMap。
>>> val map: LinkedHashMap<Int, String> = linkedMapOf() >>> map {} >>> map[1]="x" >>> map {1=x}
linkedMapOf(vararg pairs: Pair<K, V>): LinkedHashMap<K, V>
建立帶二元組Pair元素的LinkedHashMap對象。直接使用的是Java中的LinkedHashMap。
>>> val map: LinkedHashMap<Int, String> = linkedMapOf(1 to "x", 2 to "y", 3 to "z") >>> map {1=x, 2=y, 3=z} >>> map[1]="a" >>> map {1=a, 2=y, 3=z}
sortedMapOf(vararg pairs: Pair<K, V>): SortedMap<K, V>
建立一個根據Key升序排序好的TreeMap。對應的是使用Java中的SortedMap。
>>> val map = sortedMapOf(Pair("c", 3), Pair("b", 2), Pair("d", 1)) >>> map {b=2, c=3, d=1}
咱們能夠直接訪問entries屬性
val entries: Set<Entry<K, V>>
獲取該Map中的全部鍵/值對的Set。這個Entry類型定義以下:
public interface Entry<out K, out V> { public val key: K public val value: V }
代碼示例
>>> val map = mapOf("x" to 1, "y" to 2, "z" to 3) >>> map {x=1, y=2, z=3} >>> map.entries [x=1, y=2, z=3]
這樣,咱們就能夠遍歷這個Entry的Set了:
>>> map.entries.forEach({println("key="+ it.key + " value=" + it.value)}) key=x value=1 key=y value=2 key=z value=3
訪問keys屬性:
val keys: Set<K>
獲取Map中的全部鍵的Set。
>>> map.keys [x, y, z]
訪問 val values: Collection<V>
獲取Map中的全部值的Collection。這個值的集合可能包含重複值。
>>> map.values [1, 2, 3]
訪問val size: Int
獲取map鍵/值對的數目。
>>> map.size 3
咱們使用get函數來經過key來獲取value的值。
operator fun get(key: K): V?
對應的操做符是[]
:
>>> map["x"] 1 >>> map.get("x") 1
若是這個key不在Map中,就返回null。
>>> map["k"] null
若是不想返回null,可使用getOrDefault函數
getOrDefault(key: K, defaultValue: @UnsafeVariance V): V
當爲null時,不返回null,而是返回設置的一個默認值:
>>> map.getOrDefault("k",0) 0
這個默認值的類型,要和V對應。類型不匹配會報錯:
>>> map.getOrDefault("k","a") error: type mismatch: inferred type is String but Int was expected map.getOrDefault("k","a") ^
containsKey(key: K): Boolean
是否包含該key。
>>> val map = mapOf("x" to 1, "y" to 2, "z" to 3) >>> map.containsKey("x") true >>> map.containsKey("j") false
containsValue(value: V): Boolean
是否包含該value。
>>> val map = mapOf("x" to 1, "y" to 2, "z" to 3) >>> map.containsValue(2) true >>> map.containsValue(20) false
component1()
component2()
Map.Entry<K, V>
的操做符函數,分別用來直接訪問key和value。
>>> val map = mapOf("x" to 1, "y" to 2, "z" to 3) >>> map.entries.forEach({println("key="+ it.component1() + " value=" + it.component2())}) key=x value=1 key=y value=2 key=z value=3
這兩個函數的定義以下:
@kotlin.internal.InlineOnly public inline operator fun <K, V> Map.Entry<K, V>.component1(): K = key @kotlin.internal.InlineOnly public inline operator fun <K, V> Map.Entry<K, V>.component2(): V = value
Map.Entry<K, V>.toPair(): Pair<K, V>
把Map的Entry轉換爲Pair。
>>> map.entries [x=1, y=2, z=3] >>> map.entries.forEach({println(it.toPair())}) (x, 1) (y, 2) (z, 3)
getOrElse(key: K, defaultValue: () -> V): V
經過key獲取值,當沒有值能夠設置默認值。
>>> val map = mutableMapOf<String, Int?>() >>> map.getOrElse("x", { 1 }) 1 >>> map["x"] = 3 >>> map.getOrElse("x", { 1 }) 3
getValue(key: K): V
當Map中不存在這個key,調用get函數,若是不想返回null,直接拋出異常,可調用此方法。
val map = mutableMapOf<String, Int?>() >>> map.get("v") null >>> map.getValue("v") java.util.NoSuchElementException: Key v is missing in the map. at kotlin.collections.MapsKt__MapWithDefaultKt.getOrImplicitDefaultNullable(MapWithDefault.kt:19) at kotlin.collections.MapsKt__MapsKt.getValue(Maps.kt:252)
getOrPut(key: K, defaultValue: () -> V): V
若是不存在這個key,就添加這個key到Map中,對應的value是defaultValue。
>>> val map = mutableMapOf<String, Int?>() >>> map.getOrPut("x", { 2 }) 2 >>> map {x=2}
iterator(): Iterator<Map.Entry<K, V>>
這個函數返回的是 entries.iterator()
。這樣咱們就能夠像下面這樣使用for循環來遍歷Map:
>>> val map = mapOf("x" to 1, "y" to 2, "z" to 3 ) >>> for((k,v) in map){println("key=$k, value=$v")} key=x, value=1 key=y, value=2 key=z, value=3
mapKeys(transform: (Map.Entry<K, V>) -> R): Map<R, V>
把Map的Key設置爲經過轉換函數transform映射以後的值。
>>> val map:Map<Int,String> = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> val mmap = map.mapKeys{it.key * 10} >>> mmap {10=a, 20=b, 30=c, -10=z}
注意,這裏的it是Map的Entry。
若是不巧,有任意兩個key經過映射以後相等了,那麼後面的key將會覆蓋掉前面的key。
>>> val mmap = map.mapKeys{it.key * it.key} >>> mmap {1=z, 4=b, 9=c}
咱們能夠看出,1 to "a"
被-1 to "z"
覆蓋掉了。
mapValues(transform: (Map.Entry<K, V>) -> R): Map<K, R>
對應的這個函數是把Map的value設置爲經過轉換函數transform轉換以後的新值。
>>> val map:Map<Int,String> = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> val mmap = map.mapValues({it.value + "$"}) >>> mmap {1=a$, 2=b$, 3=c$, -1=z$}
filterKeys(predicate: (K) -> Boolean): Map<K, V>
返回過濾出知足key判斷條件的元素組成的新Map。
>>> val map:Map<Int,String> = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map.filterKeys({it>0}) {1=a, 2=b, 3=c}
注意,這裏的it元素是Key。
filterValues(predicate: (V) -> Boolean): Map<K, V>
返回過濾出知足value判斷條件的元素組成的新Map。
>>> val map:Map<Int,String> = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map.filterValues({it>"b"}) {3=c, -1=z}
注意,這裏的it元素是value。
filter(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V>
返回過濾出知足Entry判斷條件的元素組成的新Map。
>>> val map:Map<Int,String> = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map.filter({it.key>0 && it.value > "b"}) {3=c}
Iterable<Pair<K, V>>.toMap(destination: M): M
把持有Pair的Iterable集合轉換爲Map。
>>> val pairList = listOf(Pair(1,"a"),Pair(2,"b"),Pair(3,"c")) >>> pairList [(1, a), (2, b), (3, c)] >>> pairList.toMap() {1=a, 2=b, 3=c}
Map<out K, V>.toMutableMap(): MutableMap<K, V>
把一個只讀的Map轉換爲可編輯的MutableMap。
>>> val map = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map[1]="x" error: unresolved reference. None of the following candidates is applicable ... error: no set method providing array access map[1]="x" ^ >>> val mutableMap = map.toMutableMap() >>> mutableMap {1=a, 2=b, 3=c, -1=z} >>> mutableMap[1]="x" >>> mutableMap {1=x, 2=b, 3=c, -1=z}
plus
minus
Map的加法運算符函數以下:
operator fun <K, V> Map<out K, V>.plus(pair: Pair<K, V>): Map<K, V> operator fun <K, V> Map<out K, V>.plus(pairs: Iterable<Pair<K, V>>): Map<K, V> operator fun <K, V> Map<out K, V>.plus(pairs: Array<out Pair<K, V>>): Map<K, V> operator fun <K, V> Map<out K, V>.plus(pairs: Sequence<Pair<K, V>>): Map<K, V> operator fun <K, V> Map<out K, V>.plus(map: Map<out K, V>): Map<K, V>
代碼示例:
>>> val map = mapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map+Pair(10,"g") {1=a, 2=b, 3=c, -1=z, 10=g} >>> map + listOf(Pair(9,"s"),Pair(10,"w")) {1=a, 2=b, 3=c, -1=z, 9=s, 10=w} >>> map + arrayOf(Pair(9,"s"),Pair(10,"w")) {1=a, 2=b, 3=c, -1=z, 9=s, 10=w} >>> map + sequenceOf(Pair(9,"s"),Pair(10,"w")) {1=a, 2=b, 3=c, -1=z, 9=s, 10=w} >>> map + mapOf(9 to "s", 10 to "w") {1=a, 2=b, 3=c, -1=z, 9=s, 10=w}
加並賦值函數:
inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pair: Pair<K, V>) inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Iterable<Pair<K, V>>) inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Array<out Pair<K, V>>) inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Sequence<Pair<K, V>>) inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(map: Map<K, V>)
代碼示例:
>>> val map = mutableMapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map+=Pair(10,"g") >>> map {1=a, 2=b, 3=c, -1=z, 10=g} >>> map += listOf(Pair(9,"s"),Pair(11,"w")) >>> map {1=a, 2=b, 3=c, -1=z, 10=g, 9=s, 11=w} >>> map += mapOf(20 to "qq", 30 to "tt") >>> map {1=a, 2=b, 3=c, -1=z, 10=g, 9=s, 11=w, 20=qq, 30=tt}
減法跟加法相似。
put(key: K, value: V): V?
根據key設置元素的value。若是該key存在就更新value;不存在就添加,可是put的返回值是null。
>>> val map = mutableMapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map {1=a, 2=b, 3=c, -1=z} >>> map.put(10,"q") null >>> map {1=a, 2=b, 3=c, -1=z, 10=q} >>> map.put(1,"f") a >>> map {1=f, 2=b, 3=c, -1=z, 10=q}
putAll(from: Map<out K, V>): Unit
把一個Map所有添加到一個MutableMap中。
>>> val map = mutableMapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> val map2 = mapOf(99 to "aa", 100 to "bb") >>> map.putAll(map2) >>> map {1=a, 2=b, 3=c, -1=z, 99=aa, 100=bb}
若是有key重複的,後面的值會覆蓋掉前面的值:
>>> map {1=a, 2=b, 3=c, -1=z, 99=aa, 100=bb} >>> map.putAll(mapOf(1 to "www",2 to "tttt")) >>> map {1=www, 2=tttt, 3=c, -1=z, 99=aa, 100=bb}
MutableMap<out K, V>.remove(key: K): V?
根據鍵值key來刪除元素。
>>> val map = mutableMapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map.remove(-1) z >>> map {1=a, 2=b, 3=c} >>> map.remove(100) null >>> map {1=a, 2=b, 3=c}
MutableMap<K, V>.clear(): Unit
清空MutableMap。
>>> val map = mutableMapOf(1 to "a", 2 to "b", 3 to "c", -1 to "z") >>> map {1=a, 2=b, 3=c, -1=z} >>> map.clear() >>> map {}
本章咱們介紹了Kotlin標準庫中的集合類List、Set、Map,以及它們擴展的豐富的操做函數,這些函數使得咱們使用這些集合類更加簡單容易。
集合類持有的是對象,而怎樣的放入正確的對象類型則是咱們寫代碼過程當中須要注意的。下一章節中咱們將學習泛型。