一周入门Kotlin(二)

来源:互联网 发布:七天网络app在哪下载 编辑:程序博客网 时间:2024/06/14 20:24

Kotlin主流集合框架

集合的框架分析

如果你想研究集合框架 那么只需要打开4个文件,如下图:

这里写图片描述

这里写图片描述

这3个文件的位置分别是:
/kotlin/Collections.kt

  • 该文件主要分析了集合的继承关系

/kotlin/collections/Collections.kt
/kotlin/collections/Sets.kt
/kotlin/collections/Maps.kt

  • 这2个文件定义了创建集合的函数

集合的声明

/kotlin/Collections.kt 的文件分析如下图:

这里写图片描述

1.如果你细心点你会发现它与java最大的区别的就是除了原有的集合,还添加了原有的集合前还会多一个Mutable前缀的接口和类。比如,有一个List接口,那么对应的就会多出一个MutableList接口。MutableList代表的是可修改元素的队列,而List是无法修改元素队列,该思想主要借鉴的是OC的集合。

2.抛弃了Mutable可变的概念,我们来谈谈单纯的集合分类,集合主要分为2类,分别是Iterable接口(你也可以说是Collection类)和Map接口。

3.你可以看下Collection体系的定义:
这里写图片描述

  • Iterable接口:主要定义迭代队列的函数
  • Collection类:主要维护队列 并判断队列中有没某个元素
  • List类:操作队列中的元素 比如获取、迭代遍历等但不能对元素进行操作
  • MutableList类:拥有List类并能够添加元素、修改元素、删除元素
  • Set/MutableSet:与List和MutableList的概念差不多。

4.接下来介绍Map体系的定义:
这里写图片描述

  • Map:对应的是java的map,其提供了3个集合(keys&values&entries ),在开发的过程中,我们可以通过entries来迭代,并且,我们不能改变Map内部的数据。
  • MutableMap:多了添加/修改/删除元素的操作。

List的创建

接下来我们要分析的是/kotlin/collections/collections.kt文件:
这里写图片描述

  • listOf(…) 创建一个不可变的队列
  • emptyList() 创建一个空队列,其返回的是List的子类 叫做EmptyList
  • mutableListOf() 创建一个可变队列
  • listOfNotNull 创建的队列中 不能插入null值元素

关于上面提到的EmptyList,其实就是一个空队列,如果你访问队列中的某个元素.

以下举个例子练习一下:

var list1 = emptyList<Int>()var list2 = listOf(1, 2, 3, 4)var list3 = mutableListOf(1,2,3,4,5)

Set的创建

接下来我们要分析的是/kotlin/collections/Sets.kt文件:
这里写图片描述

  • emptySet() 创建一个空的set集合
  • setOf(…) set集合创建函数
  • mutableSetOf() 可变的set集合创建函数
  • linkedSetOf() set链表集合函数
  • Set还有个子类叫EmptySet,它就是一个空队列。

以下举个例子练习一下:

var set1 = emptySet<Int>()var set2 = setOf(1, 2, 3,4)var set3 = mutableSetOf(1,2,3,4,5)

Map的创建

这里写图片描述

不出所料 上面蓝色的部分就是map的创建函数。而红色的部分则是对接口进行函数的真正定义,如果你对扩展类的操作符(operator)有了解的话。

map的创建有很多种,这里列举可能会用到的几种:

//最简单粗暴的创建方式var map1 = mapOf(        Pair("key1", "value1"),        Pair("key2", "value2"))//简单变化1var map2 = mapOf(        "key1" to "value1",        "key2" to "value2")

集合的实践派

易错点1

你可能认为List是一个不变的对象,比如下面的代码,你认为它会出错,实际上不会。它只是让mDatas重新引用了一个新的队列。

var mDatas: List<Int> = emptyList()mDatas = listOf(1,2,3)

易错点2

这里不允许对一个不可变的List修改元素的内容.必须使用MutableList代替,也就是说如果你觉得创建一个队列需要修改它的内容,那么必须是可变的队列,而如果一个队列如果不变就尽量使用不可变队列,这样效率高点。

var mDatas: List<Int> = listOf(1,2,3)mDatas[2]=15

修改如下:

var mDatas: MutableList<Int> = mutableListOf(1,2,3)mDatas[2]=15

Map同样如此,默认是无法改变元素内容的。如你想改变元素内容,应该使用MutableMap.

var mDatas= mutableMapOf(        Pair("key1","value1"),        Pair("key2","value2"),        Pair("key3","value3"))mDatas["key1"]="newValue"

易错点3

以下我使用了增强型for循环来遍历子元素,但是请记住 不要再for的()中使用var/var关键字,这是不允许的

var mDatas: Set<Int> = setOf(1,2,3)for(index :Int in mDatas){    Log.i("IT520",""+index)}

如果我们想根据键值对来遍历map,那么在遍历的过程中就要声明两个变量,那么此刻代码应该按如下操作:

var mDatas = mapOf(        Pair("key1","value1"),        Pair("key2","value2"),        Pair("key3","value3"))for((key,value) in mDatas){    Log.i("IT520","$key --- $value")}

易错点4

对于列表来说,你可能要获取某个索引下的控件,比如如下调用elementAt,但是如果你传入找不到的索引,则会报异常:

var mDatas = listOf(1, 2, 3, 4, 5)Log.i("IT520",""+mDatas.elementAt(6))

当然,比如我们想找到第一个元素first/最后一个元素last,如果找不到也会直接报异常,如下:

var mDatas2:List<Int> = emptyList()//Log.i("IT520", "" + mDatas2.first())Log.i("IT520", "" + mDatas2.last())

上面的代码解决起来也比较简单,因为系统还提供了一些可替代的函数,如:elementAtOrElse(如果找不到则给出默认)/elementAtOrNull(如果找不到则返回null)/firstOrNull/lastOrNull等。

Kotlin数学操作符

再强调次 下面的代码要多敲

以下主要介绍加法plus/减法/minus和取反not,代码如下:

var a: Int = 3a = a.plus(5)Log.i("IT520"," $a ")a = a.minus(2)Log.i("IT520"," $a ")var flag:Boolean =falseLog.i("IT520","${flag.not()}")

有时候 我们需要做自增/自减的,代码如下:

var a: Int = 3a = a.inc() //a++   inc 代表 increaseLog.i("IT520", " $a ")a = a.dec() //a--   dec 代表 decreaseLog.i("IT520"," $a ")

除了加减 还有乘除和取余,代码如下:

//乘法  times=倍数var c = a.times(b)Log.i("IT520", "$c")//除法 divide=平均var d = a.div(b)Log.i("IT520", "$d")//取余 rem/mod 如果除数和被除数都是正数的话 那么这2个函数效果一样var e = a.rem(b)Log.i("IT520", "$e")

如果想判断某个队列中是否不存在某个元素,java提供了contains方法,kotlin中可以使用in关键字,代码如下:

var a = listOf(1, 2, 3, 4, 5)//a 容器里不存在3 返回的是BooleanLog.i("IT520", "${3 !in a}")

该关键字也可以用来判断某个字符串中是否存在某个子字符串:

var str = "Hello world !"Log.i("IT520", "${"Hello" in str}")

控制流运算符

三目运算符是我们用的比较的一个技术,这里主要介绍他的替代方案

Kotlin中,三目运算符很麻烦,但是我们可以使用if语句来代替:

var a: Int = 8var b: Int = 6//str = a>b ? "HHH" : "KKK"var str = if (a > b) "HHH" else "KKK"

在控制流程中的语句中变化最大的属于switch语句,现在改为when了:

var x = 3when (x) {   1 -> Log.i("IT520","1")   2 -> Log.i("IT520","2")   else -> { // 注意这个语句块       Log.i("IT520","else")   }}

当case内部是多条代码语句时,可以改写如下:

var x = 3when (x) {    1 -> {        Log.i("IT520","1")        Log.i("IT520","some code")    }    2 -> {        Log.i("IT520","2")        Log.i("IT520","some code")    }    else -> { // 注意这个语句块        Log.i("IT520","else")        Log.i("IT520","some code")    }}

如果有多个条件合并呢,可以这样:

var x = 1when (x) {     0,1 -> Log.i("IT520","x == 0 or x == 1")     else -> Log.i("IT520","otherwise")}

其实case语句还能支持各种条件,他可不是单纯的Int类型数据了,如下代码,感觉屌屌的:

var x = "Hello"when (x) {    in "Hello Android !" -> Log.i("IT520","Hello Android ! contains Hello str")    else -> Log.i("IT520","otherwise")}

如果你要判断某个数据在某个范围,也可以这么写:

var x = 3when (x) {    in 1..10 -> Log.i("IT520","range 1 to 10")    else -> Log.i("IT520","otherwise")}

修饰符

在java开发中,修饰符无非3中,从小到大分别的private,protected,public.而kotlin的修改符达到了4种,多了一个internal。一下介绍他们的用法:

  1. private:该修饰符修饰的类只能在本文件内使用,当然kotlin一般在一个文件可以共享很多类,也就是不一定只有本身的类才能访问该类,只要是同个文件中其他所有的类,都可以访问该被修饰的类。
  2. protected: 一般用在成员变量里面,只有本身的类或者其子类才能访问该属性,这点与java相同。
  3. internal:在安卓中,只能是同个module才能访问到该类,但具体还要看其他修饰符,如果某个类内部有个属性叫private internal,那么 其他类也是无法访问到它的。
  4. public: 在kotlin中,默认就是public修饰符,简单对外开放。提高了我们的开发效率。

匿名内部类&初涉Lambda

如果你在Android中为一个按钮设置点击事件,那么就必须调用onClick方法并在该方法中处理,为此,我们不惜代价创建了一个匿名内部类,以下就是Kotlin写法:

simple_btn.setOnClickListener(object : View.OnClickListener {    override fun onClick(v: View?) {        toast("I was clicked !")    }})

如果只想调用某个接口(而且接口内部也就只有一个函数,我们称之为单函数接口)内部的方法,我们可以使用Lambda表达式,上面的代码改进后是这样的:

simple_btn.setOnClickListener({ view ->    toast("I was clicked !")    toast("I was clicked2 !")})

你有没发现,这里我的打印压根没使用到参数view,所以view ->都可以去掉,此刻{}内部只有两句代码,也就是一个代码块。如果发现最后的参数只是一个简单的函数 我们可以将函数内部的{}抽到()后面:

simple_btn.setOnClickListener(){    toast("I was clicked !")    toast("I was clicked2 !")}

有没发现参数里面啥都没,根据最简原则,参数是可以去掉的,所以,代码应该是这样的:

simple_btn.setOnClickListener {    toast("I was clicked !")    toast("I was clicked2 !")}

下面我创建了一个接口对象,并使用invoke函数间接调用内部的方法:

var itemClickListener = {    Log.i("IT520","I was Click")    Log.i("IT520","I was Click2")}itemClickListener.invoke()
原创粉丝点击