Kotlin中的集合框架

博客地址:sguotao.top/Kotlin-2018…html

欲善其事,必利其器,在Java中集合框架占有很重要的地位,在Kotlin中也一样,想要可以在使用这些集合的时候,可以根据现实中的业务场景,信手拈来,就须要对这些集合有比较全面的了解。本篇将对比Java中的集和框架,对Kotlin中的集合框架进行梳理,首先简单回顾一下Java中的集合框架,接着重点介绍Kotlin中的集合框架,最后介绍Kotlin提供的一些关于集合框架的高阶函数。java

Java中的集合框架

集合框架的用途是提供一个容器,用来存储对象,具体使用哪一个容器,须要根据业务场景的需求,选择合适的容器。若是从容器的用途这个角度,Java提供了两种容器,Collection和Map,Collection是用来存储单个元素形式对象的集合,Map是用来存储键/值映射这样成对元素的集合。了解了这个后,再来看一下Java集合框架的全家福。 bash

20181031154096967157812.png

从图中能够看到咱们经常使用的集合如LinkedLlist、ArrayList、HashSet、HashMap等清晰的继承关系,Java将一些对集合经常使用的方法封装在Collections和Arrays两个类中。集合均可以产生一个迭代器,List还能产生一个ListIterator的迭代器。最后简单对Java的集合框架总结一下:框架

  1. Java提供了两种类型的容器,Collection和Map;
  2. 经常使用的集合List和Set都是Collection接口的实现类,List存储的对象之间有指定的顺序,存储的对象能够重复,Set存储的对象之间没有指定的顺序,存储的对象不能够重复。

Kotlin中的集合框架

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

20181031154096969715136.png

了解了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 })
复制代码

学习资料

  1. Kotlin Bootcamp for Programmers
  2. Kotlin Koans