Kotlin学习笔记(二)集合

本来这节不应该放这里的,因为在公司做一个小项目练手的时候碰到了些坑,使用了一个List,结果怎么也找不到添加item的方法,就先恶补了一下。
  首先Kotlin中的集合具有可变性和不可变性的区别,来看一下Kotlin中的相关接口:

Iterable MutableIterable
Collection MutableCollection
List MutableList
Set MutableSet
Map MutableMap

首先说明一下,这个表格并不代表继承关系,只是区分可变不可变。继承关系如下图,原谅我画的比较丑:

Kotlin集合继承关系.jpg
  • Iterable:父类。所有可以遍历的集合都是实现这个接口。只声明了iterator()一个方法,返回一个Iterator。
  • MutableIterable:重写了父类的iterator()方法,返回一个MutableIterable。
  • Collection:这个类是一个范性集合。仅包含集合是否为空,是否包含某元素等几个方法,有兴趣的可以看源码,是只读集合,不可变。
  • MutableCollection:在Collection的基础上提供了额外的函数,比如 add 、 remove 、 clear 等等,是可变集合。
  • List:它是一个范性有序的集合。因为它的有序,我们可以使用 get 函数通过position来访问,继承于Collection,只读集合。
  • MutableList:一个支持增加和删除item的List,可变集合。
  • Set:一个无序并不支持重复item的集合。
  • MutableSet:一个支持增加和删除item的Set。
  • Map:一个key-value对的集合。key在map中是唯一的,也就是说不能有两对key是一样的键值对存在于一个map中。
  • MutableMap:一个支持增加和删除item的map。增加了put和remove方法。
      附上源码中的结构图:
1.png
2.png
3.png
4.png

另外,kotlin中封装了很多常用的操作符,学会使用的话可以节省我们很多的代码量。

总数操作符

any
如果至少有一个元素符合给出的判断条件,则返回true。
all
如果全部的元素符合给出的判断条件,则返回true。
count
返回符合给出判断条件的元素总数。
fold
在一个初始值的基础上从第一项到最后一项通过一个函数累计所有的元素。
foldRight
与 fold 一样,但是顺序是从最后一项到第一项。
forEach
遍历所有元素,并执行给定的操作。
forEachIndexed
与 forEach 类似,但是我们同时可以得到元素的index。类似的还有foldIndexed和foldRightIndexed。
max
返回最大的一项,如果没有则返回null。min同理。
maxBy
根据给定的函数返回最大的一项(返回的是集合本身的元素,而非给定函数运算过结果),如果没有则返回null。minBy同理。
none
如果没有任何元素与给定的函数匹配,则返回true。
reduce
reduce系列类似fold系列,包括reduceIndexed、reduceRight、reduceRightIndexed,只是没有初始值。
sumBy
返回所有每一项通过函数转换之后的数据的总和。

    val list = listOf(1, 2, 3, 4, 5, 6)

    println(list.any { it > 5 })//true
    println(list.all { it > 1 })//false
    println(list.count { it > 3 })//3
    println(list.fold(5) { total, next -> total + next })//5+1+2+3+4+5+6=26
    println(list.fold(5) { total, next -> total * next })//5*1*2*3*4*5*6=3600
    println(list.fold("5") { total, next -> total + next })//"5"+1+2+3+4+5+6="5123456"
    println(list.foldRight(5) { total, next -> total + next })//"5"+1+2+3+4+5+6="5123456"
    list.forEach { print(it) }//123456
    list.forEachIndexed { index, i -> print("$index:$i,") }//0:1,1:2,2:3,3:4,4:5,5:6,
    println(list.max())//6
    println(list.maxBy { it * -1 })//1
    println(list.none { it > 6 })//true
    println(list.reduce { acc, i -> acc + i })//21
    println(list.sumBy { it * -1 })//-21

过滤操作符

drop
返回去掉前n个元素的剩余元素的列表。
dropLast
返回去掉后n个元素的剩余元素的列表。
dropWhile
返回根据给定函数从第一项开始去掉指定元素的列表。即从前面开始,符合条件的一律去除,直到碰到一个不符合条件的元素为止。
dropLastWhile
返回根据给定函数从最后一项开始去掉指定元素的列表。
filter
过滤所有符合给定函数条件的元素。filterIndexed同filter,同时返回索引。
filterNot
过滤所有不符合给定函数条件的元素。
filterNotNull
过滤所有元素中不是null的元素。
slice
过滤一个list中指定index的元素。
take
返回从第一个开始的n个元素。takeLast从最后一个开始返回n个。
takeWhile
返回从第一个开始符合给定函数条件的元素,一旦不符合即停止。takeLastWhile从最后一个开始返回。
takeIf
如果满足条件,则返回这个集合,注意参数it代表的是集合,而非集合中的元素。takeUnless相反,如果满足条件,则返回null,否则返回集合本身。

    val list = listOf(1, 2, 3, 4, 5, 6)
    println(list.drop(2))//[3, 4, 5, 6]
    println(list.dropLast(2))//[1, 2, 3, 4]
    println(list.dropWhile { it > 2 })//[1, 2, 3, 4, 5, 6]
    println(list.dropLastWhile { it > 2 })//[1, 2]
    println(list.filter { it > 3 })//[4, 5, 6]
    println(list.filterIndexed { index, i -> i > 3 && index > 4 })//[6]
    println(list.filterNot { it > 3 })//[1, 2, 3]
    println(list.filterNotNull())//[1, 2, 3, 4, 5, 6]
    println(list.slice(1..2))//[2, 3]
    println(list.take(3))//[1, 2, 3]
    println(list.takeLast(3))//[4, 5, 6]
    println(list.takeWhile { it > 3 })//[]
    println(list.takeLastWhile { it > 3 })//[4, 5, 6]
    println(list.takeIf { it.isNotEmpty() })//[1, 2, 3, 4, 5, 6]
    println(list.takeUnless { it.isNotEmpty() })//null

映射操作符

flatMap
遍历所有的元素,为每一个创建一个集合,最后把所有的集合放在一个集合中。
groupBy
返回一个根据给定函数分组后的map。
map
返回一个每一个元素根据给定的函数转换所组成的List。mapIndexed同理,同时可以操作每一个元素的索引。
mapNotNull
返回一个每一个非null元素根据给定的函数转换所组成的List。mapIndexedNotNull同理。

    val list = listOf(1, 2, 3, 4, 5, 6)
    println(list.flatMap { listOf(it + 1) })//[2, 3, 4, 5, 6, 7]
    println(list.groupBy { it % 2 == 0 })//{false=[1, 3, 5], true=[2, 4, 6]}
    println(list.map { it * it })//[1, 4, 9, 16, 25, 36]
    println(list.mapNotNull { it?.times(2) })//[2, 4, 6, 8, 10, 12],如果list改为listOf(1, 2, 3, 4, 5, null),则返回[2, 4, 6, 8, 10]

元素操作符

contains
如果指定元素可以在集合中找到,则返回true。
elementAt
返回给定index对应的元素,如果index数组越界则会抛出 IndexOutOfBoundsException 。
elementAtOrElse
返回给定index对应的元素,如果index数组越界则会根据给定函数返回默认值。
elementAtOrNull
返回给定index对应的元素,如果index数组越界则会返回null。
first
返回符合给定函数条件的第一个元素。
firstOrNull
返回符合给定函数条件的第一个元素,如果没有符合则返回null。
indexOf
返回指定元素的第一个index,如果不存在,则返回 -1 。
indexOfFirst
返回第一个符合给定函数条件的元素的index,如果没有符合则返回 -1 。
indexOfLast
返回最后一个符合给定函数条件的元素的index,如果没有符合则返回 -1 。
last
返回符合给定函数条件的最后一个元素。
lastIndexOf
返回指定元素的最后一个index,如果不存在,则返回 -1 。
lastOrNull
返回符合给定函数条件的最后一个元素,如果没有符合则返回null。
single
返回符合给定函数的单个元素,如果没有符合或者超过一个,则抛出异常。
singleOrNull
返回符合给定函数的单个元素,如果没有符合或者超过一个,则返回null。
  这一部分与java中的集合操作类似,基本看字面就可以理解什么意思,应该也是最常用的一些操作符了。

生产操作符

partition
把一个给定的集合分割成两个,第一个集合是由原集合每一项元素匹配给定函数条件返回 true 的元素组成,第二个集合是由原集合每一项元素匹配给定函数条件返回 false 的元素组成。
plus
返回一个包含原集合和给定集合中所有元素的集合,因为函数的名字原因,我们可以使用 + 操作符。
zip
返回由 pair 组成的List,每个 pair 由两个集合中相同index的元素组成。这个返回的List的大小由最小的那个集合决定。
unzip
从包含pair的List中生成包含List的Pair。

    val list1 = listOf(1, 2, 3)
    val list2 = listOf(4, 5, 6)
    println(list1.partition { it % 2 == 0 })//([2], [1, 3])
    println(list1.plus(list2))//[1, 2, 3, 4, 5, 6]
    println(list1 + list2)//[1, 2, 3, 4, 5, 6]
    println(list1.zip(list2))//[(1, 4), (2, 5), (3, 6)]
    println(listOf(Pair(1, 2), Pair(3, 4)).unzip())//([1, 3], [2, 4])

顺序操作符

reverse
返回一个与原list反序的list。
sort
返回一个原list升序排列后的list。
sortBy
返回一个根据指定函数升序排序后的list。
sortDescending
返回一个原list降序排序后的List。
sortDescendingBy
返回一个根据指定函数降序排序后的list。

    val list = listOf(1, 2, 3, 4, 5, 6)
    println(list.reversed())//[6, 5, 4, 3, 2, 1]
    println(list.sorted())//[1, 2, 3, 4, 5, 6]
    println(list.sortedBy { it % 6 })//[6, 1, 2, 3, 4, 5]
    println(list.sortedDescending())//[6, 5, 4, 3, 2, 1]
    println(list.sortedByDescending { it % 6 })//[5, 4, 3, 2, 1, 6]

注意上述所有操作符的测试环境为List,而非MutableList,即上述操作符并不会改变原集合本身。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容