测试项目Github地址:

KotlinForJava

前文传送:

Kotlin入门第一课:从对比Java开始

初次尝试用Kotlin实现Android项目

1. 介绍

作为Kotlin入门的第二课,不打算按照教程从基础数据类型开始,而是直接学习至关重要的集合部分。因为一般的应用开发都离不开数据,数据处理就要用到集合,而只有深入了解集合,包括概念及不同类型的集合分别实现了哪些方法,才能在需要的时候快速选出最合适的集合与对应的操作。因此,迫不及待地想给大家展示Kotlin集合的魅力,基础数据类型的用法会放到后续的文章进行整理。

Kotlin中的集合主要有以下几种:

Iterable--An iterator over a collection or another entity that can be represented as a sequence of elements;

MutableIterable--An iterator over a mutable collection. Provides the ability to remove elements while iterating;

Collection--A generic collection of elements. Methods in this interface support only read-only access to the collection;

MutableCollection--A generic collection of elements that supports adding and removing elements;

List--A generic ordered collection of elements. Methods in this interface support only read-only access to the list;

MutableList--A generic ordered collection of elements that supports adding and removing elements;

Set--A generic unordered collection of elements that does not support duplicate elements;

MutableSet--A generic unordered collection of elements that does not support duplicate elements, and supports adding and removing elements;

Map--A collection that holds pairs of objects (keys and values) and supports efficiently retrieving the value corresponding to each key. Map keys are unique; the map holds only one value for each key;

MutableMap--A modifiable collection that holds pairs of objects (keys and values) and supports efficiently retrieving the value corresponding to each key. Map keys are unique; the map holds only one value for each key;

不专业的翻译会误导读者,所以这里就不献丑了,相信这段英文解释对程序员来说不成问题。

2. 操作方法

涉及到的代码在KotlinForJava的Kotlin1项目中,针对集合List和MutableList的操作进行测试,参考的是Kotlin中文学习资料,前面给出的文章中能找到相应的资源链接。

学习的同时通过编码练习是很有必要的,除了加深理解还可以发现资料中存在的问题,常见的如IDEA或API更新了而资料是旧的,花时间去学习已经废弃的方法就不值得了。所以,建议英文好的通过官网给出的资料来学习是最好的,上面的信息一般会及时更新。

先定义两个List对象,后面的操作会用到。

 val list = listOf(, , , , , , , , , )
val mutableList = mutableListOf(, , , , , , , , , )

2.1 总数操作

测试代码:

 println(list.any { it %  ==  })

 println(list.all { it %  ==  })

 println(list.count { it %  ==  })

 println(list.fold() { total, next -> total + next })
println(list.foldRight() { total, next -> total + next }) list.forEach { value -> if (value > ) println(value) }
list.forEachIndexed { index, value -> if (value > ) println("value of index $index is $value") } println(list.max())
println(list.maxBy { -it }) println(list.min())
println(list.minBy { -it }) println(list.none { it % == }) println(list.reduce { total, next -> total + next })
println(list.reduceRight { total, next -> total + next }) println(list.sumBy { it % })

方法作用:

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--获取方法处理后返回结果值的总和;

建议将文字解释和代码结合起来理解方法的作用,先对结果有一个预判,然后看下面的打印信息。

打印结果:

true
false value of index is true

2.2 过滤操作

测试代码:

 println(list.drop())
println(list.dropWhile { it < })
println(list.dropLastWhile { it < }) println(list.filter { it % == })
println(list.filterNot { it % == })
println(list.filterNotNull()) println(list.slice(listOf(, , )))
//println(list.slice(listOf(0, 4, 80))) //java.lang.ArrayIndexOutOfBoundsException: 80 println(list.take())
println(list.takeLast())
println(list.takeWhile { it < })

方法作用:

drop--返回去掉前n个元素后的列表;
dropWhile--返回从第一项起,去掉满足条件的元素,直到不满足条件的一项为止;
dropLastWhile--返回从最后一项起,去掉满足条件的元素,直到不满足条件的一项为止;

filter--过滤掉所有不满足条件的元素;
filterNot--过滤掉所有满足条件的元素;
filterNotNull--过滤掉所有值为null的元素;

slice--过滤掉非指定下标的元素,即保留下标对应的元素过滤List中指定下标的元素(比如这里只保留下标为1,3,4的元素),当过滤list中有元素值大于目标List大小时会出现异常;

take--返回从第一个开始的n个元素;
takeLast--返回从最后一个开始的n个元素;
takeWhile--返回不满足条件的下标前面的所有元素的集合;

代码中有一行注释,关于slice操作,在实际使用时需要注意过滤List中的元素值,以免出现ArrayIndexOutOfBoundsException异常。

打印结果:

[, , , , , ]
[]
[, , , , , , , , , ]
[, , , , ]
[, , , , ]
[, , , , , , , , , ]
[, , ]
[, ]
[, ]
[, , ]

2.3 映射操作

测试代码:

 println(list.flatMap { listOf(it, it + ) })

 println(list.groupBy { if (it %  == ) "even" else "odd" })

 println(list.map { it *  })
println(list.mapIndexed { index, it -> index * it })
println(list.mapNotNull { it * })

方法作用:

flatMap--合并两个集合,可以在合并的时候对迭代元素值it多想要的操作;

groupBy--将集合中的元素按照某个条件分组,返回Map;

map--将集合中的元素通过某个方法转换后的结果存到一个集合中;
mapIndexed--除了得到转换后的结果,还可以拿到index(下标);
mapNotNull--执行方法转换前过滤掉为null的元素;

打印结果:

[, , , , , , , , , , , , , , , , , , , ]
{even=[, , , , ], odd=[, , , , ]}
[, , , , , , , , , ]
[, , , , , , , , , ]
[, , , , , , , , , ]

2.4 元素操作

测试代码:

 println(list.contains())

 println(list.elementAt())
//println(list.elementAt(11)) //java.lang.ArrayIndexOutOfBoundsException: 11
println(list.elementAtOrElse(, { * it }))
println(list.elementAtOrNull()) println(list.first { it % == })
//println(list.first { it % 2 == 10 }) //java.util.NoSuchElementException: Collection contains no element matching the predicate
println(list.firstOrNull() { it % == }) println(list.indexOf())
println(list.indexOfFirst { it % == })
println(list.indexOfLast { it % == }) println(list.last { it % == })
//println(list.last { it % 2 == 10 }) //java.util.NoSuchElementException: List contains no element matching the predicate
println(list.lastIndexOf())
println(list.lastOrNull { it % == }) println(list.single { it % == })
//println(list.single { it % 2 == 0 }) //java.lang.IllegalArgumentException: Collection contains more than one matching element
println(list.singleOrNull() { it % == })

方法作用:

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。

打印结果:

true

null

null

null

null

2.5 生产操作

测试代码:

 println(list.partition { it %  ==  })

 println(list + listOf(, ))

 println(list.zip(listOf(, )))
println(listOf(Pair(, ), Pair(, )).unzip())

方法作用:

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后的版本开始就弃用了。

打印结果:

([, , , , ], [, , , , ])
[, , , , , , , , , , , ]
[(, ), (, )]
([, ], [, ])

2.6 排序操作

测试代码:

 println(list.reversed())

 println(list.sorted())
println(list.sortedBy {it % }) println(list.sortedDescending())
println(list.sortedByDescending { it % })

方法作用:

reversed--相反顺序;
sorted--自然排序(升序);
sortedBy--根据方法处理结果进行自然(升序)排序;
sortedDescending--降序排序;
sortedByDescending--根据方法处理结果进行降序排序;

注意:新版kotlin需要调用sorted()这样带"ed"后缀的方法才能返回List,而sort()是返回Unit。那么这两种方法还有哪些区别,或者说分别在什么场景下使用?

还是以sort为例,sorted()处理过程中会新建临时的List来保存结果数据,对原来的调用者List不会做任何改变,所以需要将新建的对象返回;而sort()是在原来的List基础上进行元素顺序的调整,不会新建对象,所以不需要返回List。

打印结果:

[, , , , , , , , , ]
[, , , , , , , , , ]
[, , , , , , , , , ]
[, , , , , , , , , ]
[, , , , , , , , , ]

开头部分还定义了一个MutableList对象,下面就结合不带"ed"后缀的排序方法对其进行操作。

1 mutableList.reverse()
2 println(mutableList)

打印输出:

[, , , , , , , , , ]

如果用list对象调用reverse()会提示List没有该方法,算是各尽其职。而将list打印出来发现果然还是初始化时的顺序:

[, , , , , , , , , ]

3. 总结

本文对集合类型List(MutableList针对排序)的总数、过滤、映射、元素、生产及排序六种操作进行了测试,指出了可能出现异常的地方,通过比较加深了List和MutableList这种对应类型的联系与区别。有些操作在Kotlin中只需一句代码就可以得到结果,而在Java中需要手动通过普通的循环或迭代器来对集合中的元素逐一进行处理。

对于Set等其他集合类型,对象创建和操作与List类似,这里不一一举出了。

Kotlin入门第二课:集合操作的更多相关文章

  1. 数据结构入门第二课(浙大mooc)

    数据结构入门第二课 目录 数据结构入门第二课 引子 多项式的表示 方法1 顺序结构表示多项式各项 方法2 顺序结构表示非零项 方法3 链表结构存储非零项 多项式问题的启示 线性表 线性表的抽象数据类型 ...

  2. Hibernate入门第二课 Hibernate Tools for Eclipse Plugins安装

    Hibernate入门第二课 Hibernate Tools for Eclipse Plugins安装 你们可以直接去,http://blog.csdn.net/wei_chong_chong/ar ...

  3. Kotlin入门第一课:从对比Java开始

    1. 介绍 今年初,甲骨文再次对谷歌所谓的安卓侵权使用Java提起诉讼,要求后者赔偿高达90亿美元.随后便传出谷歌因此计划将主力语言切换到苹果主导的Swift,不过这事后来没了跟进. 但谷歌在这两天的 ...

  4. Kotlin入门(27)文件读写操作

    Java的文件处理用到了io库java.io,该库虽然功能强大,但是与文件内容的交互还得通过输入输出流中转,致使文件读写操作颇为繁琐.因此,开发者通常得自己重新封装一个文件存取的工具类,以便在日常开发 ...

  5. Kotlin入门(4)声明与操作数组

    上一篇文章介绍了基本变量类型在Kotlin中的用法,不过这只针对单个变量,如果要求把一组相同类型的变量排列起来,形成一个变量数组,那又该如何声明和操作呢? 在Java中声明数组,跟在C语言中声明是一样 ...

  6. Spring入门第二课:Spring配置Bean的细节

    1.配置bean的作用域: 通过配置scope属性可以bean的作用域,参数有 prototype.request.session.singleton. 1)singleton为单例,IoC容器只会创 ...

  7. MySQL入门第二天——记录操作与连接查询

    常见SQL语法,请参见w3school:http://www.w3school.com.cn/sql/sql_distinct.asp 易百教程:http://www.yiibai.com/sql/f ...

  8. Spring入门第二课

    看代码 package logan.spring.study; public class HelloWorld { private String name; public void setName2( ...

  9. mysql 第二课 DML操作

    DML 数据操纵语句:INSERT UPDATE DELETE SELECT 主要用来对数据库的数据进行一些操作; DCL 数据定义语句:CREATE ALTER DROP  主要是用在定义或改变表的 ...

随机推荐

  1. sqoop 操作从hdfs 导入到mysql中语句

    将hdfs下/dw/dms/usr_trgt下的文件导入到mysql中test数据库下usr_trgt表中 sqoop-export   --connect jdbc:mysql://mysqlDB: ...

  2. 实现一个竖直的显示表头的表格(vue版本)

    今天遇到一个问题,实现这样一个竖直的显示表头的表格,如下图.默认显示两列. vue实现代码如下:   tableComponent.vue:   <template> <table ...

  3. JQuery分页插件封装(源码来自百度,自己封装)

    最近由于项目的需要,做了一个基于JQuery的表格分页插件封装,部分源码来源百度,经由自己封装完成. 下面是具体代码和说明,仅供参考.第一步可以先将我的HTML,CSS,JS这三部分的代码创建好后先运 ...

  4. MySQL执行计划总结

    背景 在工作过程中,最近时常对慢查询进行调优.对于MySQL的SQL语句调优,MySQL本身提供了强大的explain关键字用于查询分析执行计划. 本文对explain执行计划进行分析与整理,文中的内 ...

  5. Objective-C 实用关键字详解1「面试、工作」看我就 🐒 了 ^_^.

    在写项目 或 阅读别人的代码(一些优秀的源码)中,总能发现一些常见的关键字,随着编程经验的积累大部分还是知道是什么意思 的. 相信很多开发者跟我当初一样,只是基本的常用关键字定义属性会使用,但在关键字 ...

  6. Mac os下安装brew

    1.首先没下载xcode,请先安装xcode,安装的继续往下面看 2.安装brew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubuser ...

  7. 【日常】C++ 的那些“坑” —— delete 与 析构函数 与 virtual 的 9 个小例子

    C++中有无数的坑,但毕竟-- 今天就踩到了,也算是基本问题了,记录一下,顺便以后可以考考自己.你也可以猜猜答案,大牛绕行. 0x1 先看这个: #include <stdio.h> #i ...

  8. Fullcalendar 日历控件的基本使用

    1:Fullcalendar 日历控件的基本简介 Fullcalendar是一款十分强大的开源日历免费控件,提供了丰富的属性设置和方法调用. 官网地址:https://fullcalendar.io/ ...

  9. redis 编译安装(生产环境推荐)

    一.安装redis 1.下载redis包 wget http://download.redis.io/releases/redis-3.2.1.tar.gz 2.解压redis包到/opt下 tar ...

  10. Docker - 容器互联

    容器互联 通过docker run命令的--link参数可以让容器之间通过连接(linking)系统进行交互. 参数格式:--link name:alias ,name是要链接的容器名称, alias ...