博客地址:sguotao.top/Kotlin-2018…html
欲善其事,必利其器,在Java中集合框架佔有很重要的地位,在Kotlin中也一樣,想要可以在使用這些集合的時候,可以根據現實中的業務場景,信手拈來,就須要對這些集合有比較全面的瞭解。本篇將對比Java中的集和框架,對Kotlin中的集合框架進行梳理,首先簡單回顧一下Java中的集合框架,接着重點介紹Kotlin中的集合框架,最後介紹Kotlin提供的一些關於集合框架的高階函數。java
集合框架的用途是提供一個容器,用來存儲對象,具體使用哪一個容器,須要根據業務場景的需求,選擇合適的容器。若是從容器的用途這個角度,Java提供了兩種容器,Collection和Map,Collection是用來存儲單個元素形式對象的集合,Map是用來存儲鍵/值映射這樣成對元素的集合。瞭解了這個後,再來看一下Java集合框架的全家福。 bash
從圖中能夠看到咱們經常使用的集合如LinkedLlist、ArrayList、HashSet、HashMap等清晰的繼承關係,Java將一些對集合經常使用的方法封裝在Collections和Arrays兩個類中。集合均可以產生一個迭代器,List還能產生一個ListIterator的迭代器。最後簡單對Java的集合框架總結一下:框架
Kotlin中的集合框架,去掉了Java中歷史遺留的一些結構,同時集合類型在Kotlin中能夠是隻讀的,也能夠是可變的,因而Kotlin中的集合框架就與Java中集合框架有以下的映射關係:dom
Java中的類型 | Kotlin中的只讀類型 | Kotlin中的可變類型 |
---|---|---|
Iterator<T> | Iterator<T> | MutableIterator<T> |
Iterable<T> | Iterable<T> | MutableIterable<T> |
Collection<T> | Collection<T> | MutableCollection<T> |
Set<T> | Set<T> | MutableSet<T> |
List<T> | List<T> | MutableList<T> |
ListIterator<T> | ListIterator<T> | MutableListIterator<T> |
Map<K, V> | Map<K, V> | MutableMap<K, V> |
Map.Entry<K, V> | Map.Entry<K, V> | MutableMap.MutableEntry<K,V> |
相應的給出Kotlin的集合框架圖,從圖中也能夠看出,Kotlin集合中的可變類型都實現了只讀類型,同時將一些對集合操做的方法,封裝在了_Collections和_Arrays等文件中。因爲Kotlin中存在擴展函數,所以在使用這些方法時,不是直接經過文件名+點的方式進行調用,而是就像集合自身的方法同樣進行調用。從Java的角度看,就像這些方法是這些集合的成員函數。 jvm
瞭解了Kotlin的集合框架,那麼實際用到的集合有哪些呢?在Kotlin collections包中能夠找到這樣一個文件TypeAliasesKt.class文件。函數
@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>
複製代碼
能夠看到,咱們經常使用的一些集合如ArrayList、LinkedHashMap、HashMap、LinkedHashSet、HashSet等,在Kotlin中實際上對應的就是Java中的這些集合,Kotlin只是換了個別名而已,這些集合的存儲結構與Java中是同樣的,因此能夠如同在Java中同樣的方式使用這些集合。工具
前面說到Kotlin將一些對集合的擴展函數都封裝在了_Collections、_Arrays這樣的文件中,那麼究竟有哪些擴展函數呢?瞭解一下,能夠省去寫不少工具方法的時間,並且穩定性可能會優於咱們本身的工具方法。因爲擴展函數數量比較多,這裏將按照函數實現的功能,將這些函數分紅下面幾類。學習
1.any 若是有一個元素符合給出的判斷條件,返回true*ui
val list = listOf(1, 2, 3, 4, 5, 6)
val listwithNull = listOf(1, 2, 3, 4, null, 5, null, 6, null)
assertTrue(list.any { it % 2 == 0 })
複製代碼
2.all 若是所有的元素符合給出的判斷條件,返回true
assertTrue { list.all { it > 0 } }
複製代碼
3.count 返回符合給出判斷條件的元素的個數
assertEquals(3, list.count { it % 2 == 0 })
複製代碼
4.fold 在一個初始值的基礎上從第一項到最後一項進行累加
assertEquals(220, list.fold(10) { total, next -> total + next * 10 })
複製代碼
5.foldRight 與fold相似,但順序是從最後一項到第一項
assertEquals(31, list.foldRight(10) { total, next -> total + next })
複製代碼
6.forEach 遍歷全部元素並執行給定操做
list.forEach() { print(it) }
複製代碼
7.forEachIndexed 與forEach相似,同時能夠獲取元素的index
list.forEachIndexed() { index, value -> println("position:$index,value:$value") }
複製代碼
8.max 返回最大一項,若是沒有返回null
assertEquals(6, list.max())
複製代碼
9.maxBy 根據給定的函數,返回最大一項,若是沒有返回null
assertEquals(1, list.maxBy { -it })
複製代碼
10.min 返回最小一項,若是沒有返回null
assertEquals(1, list.min())
複製代碼
11.minBy 根據給定的函數,返回最小的一項,若是沒有返回null
assertEquals(6, list.minBy { -it })
複製代碼
12.none 若是沒有任何元素與給定的函數匹配,返回true
assertTrue { list.none() { it >= 7 } }
複製代碼
13.reduce 與fold相似,但沒有初始值
assertEquals(21, list.reduce() { total, next -> total + next })
複製代碼
14.reduceRight 與reduce相似,但順序是從最後一項到第一項
assertEquals(21, list.reduceRight() { total, next -> total + next })
複製代碼
15.sumBy 返回每一項經過函數轉換後的數據總和
assertEquals(-21, list.sumBy { -it })
複製代碼
16.drop 返回包含去掉前n個元素的全部元素的列表
assertEquals(listOf(5, 6), list.drop(4))
複製代碼
17.dropWhile 返回去掉知足指定函數要求的,從第一個元素開始的全部元素的列表
assertEquals(listOf(4, 5, 6), list.dropWhile { it < 4 })
複製代碼
18.dropLastWhile 返回去掉指定函數要求的,從最後一個元素開始的全部元素的列表
assertEquals(listOf(1, 2, 3, 4), list.dropLastWhile { it > 4 })
複製代碼
19.filter 保留全部知足指定函數要求的元素
assertEquals(listOf(2, 4, 6), list.filter { it % 2 == 0 })
複製代碼
20.filterNot 過濾掉全部知足指定函數要求的元素
assertEquals(listOf(1, 3, 5), list.filterNot { it % 2 == 0 })
複製代碼
21.filterNotNull 保留全部不爲null的元素
assertEquals(listOf(1, 2, 3, 4, 5, 6), listwithNull.filterNotNull())
複製代碼
22.slice 保留list中指定index的元素
assertEquals(listOf(2, 4, 5), list.slice(listOf(1, 3, 4)))
複製代碼
23.take 保留從第一個元素開始的n個元素
assertEquals(listOf(1, 2, 3), list.take(3))
複製代碼
24.takeLast 保留從最後一個元素開始的n個元素
assertEquals(listOf(4, 5, 6), list.takeLast(3))
複製代碼
25.takeWhile 保留從第一個元素開始,知足指定函數的元素
assertEquals(listOf(1, 2), list.takeWhile { it < 3 })
複製代碼
26.flatMap 遍歷每個元素,爲每個元素建立一個集合,最後把全部集合合併爲一個集合
print(list)//list:[1,2,3,4,5,6]
//[1,2],[2,3],[3,4],[4,5],[5,6],[6,7] => [1,2,2,3,3,4,4,5,5,6,6,7]
println(list.flatMap { listOf(it, it + 1) })
複製代碼
27.groupBy 返回一個根據指定函數分組的map
println(mapOf("odd" to listOf(1, 3, 5)))
println(mapOf("even" to listOf(2, 4, 6)))
println(list.groupBy { if (it % 2 == 0) "even" else "odd" })
複製代碼
28.map 返回一個,每一個元素都按照指定函數進行轉換後的集合
assertEquals(listOf(2, 4, 6, 8, 10, 12), list.map { it -> it * 2 })
複製代碼
29.mapIndexed 返回一個,每一個元素按照包含元素index的指定函數轉換後的集合
assertEquals(listOf(0, 2, 6, 12, 20, 30), list.mapIndexed { it, index -> index * it })
複製代碼
30.mapNotNull 返回一個過濾掉null元素,而且非null元素按照指定函數進行轉換後的集合
println(listwithNull)
println(listwithNull.mapNotNull { it })
複製代碼
31.contains 若是指定元素在集合中,返回true
assertTrue(list.contains(1))
複製代碼
32.elementAt 返回指定index對應的元素,若是index越界,拋IndexOutOfBoundsException
assertEquals(1, list.elementAt(0))
複製代碼
33.elementAtOrElse 返回指定index對應的元素,若是index越界,返回指定函數中設置的默認值
assertEquals(20, list.elementAtOrElse(10, { 2 * it }))
複製代碼
34.elementAtOrNull 返回指定index對應的元素,若是index越界,返回null
assertNull(list.elementAtOrNull(10))
複製代碼
35.first 返回第一個知足指定函數的元素,若是沒有,拋出NoSuchElementException
assertEquals(2, list.first() { it % 2 == 0 })
複製代碼
36.firstOrNull 返回第一個知足指定函數的元素,若是沒有返回null
assertNull(list.firstOrNull() { it < 0 })
複製代碼
37.indexOf 返回指定元素的第一個index,若是不存在返回-1
assertEquals(-1, list.indexOf(7))
複製代碼
38.indexOfFirst 返回第一個知足指定函數的元素的index,若是不存在返回-1
assertEquals(1, list.indexOfFirst { it % 2 == 0 })
複製代碼
39.indexOfLast 返回最後一個知足指定函數的元素的index,若是不存在返回-1
assertEquals(5, list.indexOfLast { it % 2 == 0 })
複製代碼
40.last 返回最後一個知足指定函數的元素,若是沒有,拋出NoSuchElementException
println(list.last() { it % 2 == 0 })
複製代碼
41.lastIndexOf 返回指定元素的最後一個index,若是不存在返回-1
println(listwithNull.lastIndexOf(null))
複製代碼
42.lastOrNull 返回最後一個知足指定函數的元素,若是沒有返回null
assertNull(list.lastOrNull() { it < 0 })
複製代碼
43.single 返回知足指定函數的單個元素,若是沒有,或者知足條件的元素個數超過一個,拋出異常
assertEquals(1, list.single() { it < 2 })
複製代碼
44.singleOrNull 返回知足指定函數的單個元素,若是沒有,或者知足條件的元素個數超過一個,返回null
println(list.singleOrNull() { it % 2 == 0 })
複製代碼
45.partition 將一個給定的集合分割成兩個集合,第一個集合是由匹配指定函數,返回true的元素組成。第二個集合是由匹配指定函數,返回false的元素組成。
assertEquals(Pair(listOf(1, 3, 5), listOf(2, 4, 6)), list.partition { it % 2 != 0 })
複製代碼
46.plus 返回一個包含原集合和給定集合中全部元素的集合,可使用「+」操做符
assertEquals(listOf(1, 2, 3, 4, 5, 6, 6, 7, 8), list + listOf(6, 7, 8))
複製代碼
47.plusElement 在集合中添加元素
println(list.plusElement(7))
複製代碼
48.zip 將兩個集合按照下標進行配對,組成的Pair是由兩個集合中相同index的元素組成,若是兩個集合長度不一致,取短的集合的長度。
assertEquals(listOf(Pair(1, 'x'), Pair(2, 'y')), list.zip(listOf('x', 'y')))
複製代碼
49.unzip 做用在包含Pair的集合上,依次取各個Pair的first和second值,放入List和List中,而後返回包含List和List的Pair
val listPair = listOf(Pair(1, 2), Pair('a', 'b'), Pair(3, 4), Pair('c', 'd'))
println(listPair)
println(listPair.unzip())
複製代碼
50.reversed 返回一個與指定list順序相反的list
println(list)
println(list.reversed())
複製代碼
51.sorted 升序排序
println(list.sorted())
複製代碼
52.sortBy 返回一個按照指定函數變換後的升序排序
println(list.sortedBy { it -> it % 3 })
複製代碼
53.sortDescending 降序排序
println(list.sortedDescending())
複製代碼
54.sortDescendingBy 返回一個按照指定函數變換後的降序排序
println(list.sortedByDescending { it -> it % 3 })
複製代碼