如果你想研究集合框架 那么只需要打开4个文件,如下图:
这3个文件的位置分别是:
/kotlin/Collections.kt
/kotlin/collections/Collections.kt
/kotlin/collections/Sets.kt
/kotlin/collections/Maps.kt
/kotlin/Collections.kt 的文件分析如下图:
1.如果你细心点你会发现它与java最大的区别的就是除了原有的集合,还添加了原有的集合前还会多一个Mutable前缀的接口和类。比如,有一个List接口,那么对应的就会多出一个MutableList接口。MutableList代表的是可修改元素的队列,而List是无法修改元素队列,该思想主要借鉴的是OC的集合。
2.抛弃了Mutable可变的概念,我们来谈谈单纯的集合分类,集合主要分为2类,分别是Iterable接口(你也可以说是Collection类)和Map接口。
接下来我们要分析的是/kotlin/collections/collections.kt文件:
关于上面提到的EmptyList,其实就是一个空队列,如果你访问队列中的某个元素.
以下举个例子练习一下:
var list1 = emptyList()
var list2 = listOf(1, 2, 3, 4)
var list3 = mutableListOf(1,2,3,4,5)
接下来我们要分析的是/kotlin/collections/Sets.kt文件:
以下举个例子练习一下:
var set1 = emptySet()
var set2 = setOf(1, 2, 3,4)
var set3 = mutableSetOf(1,2,3,4,5)
不出所料 上面蓝色的部分就是map的创建函数。而红色的部分则是对接口进行函数的真正定义,如果你对扩展类的操作符(operator)有了解的话。
map的创建有很多种,这里列举可能会用到的几种:
//最简单粗暴的创建方式
var map1 = mapOf(
Pair("key1", "value1"),
Pair("key2", "value2")
)
//简单变化1
var map2 = mapOf(
"key1" to "value1",
"key2" to "value2"
)
你可能认为List是一个不变的对象,比如下面的代码,你认为它会出错,实际上不会。它只是让mDatas重新引用了一个新的队列。
var mDatas: List = emptyList()
mDatas = listOf(1,2,3)
这里不允许对一个不可变的List修改元素的内容.必须使用MutableList代替,也就是说如果你觉得创建一个队列需要修改它的内容,那么必须是可变的队列,而如果一个队列如果不变就尽量使用不可变队列,这样效率高点。
var mDatas: List = listOf(1,2,3)
mDatas[2]=15
修改如下:
var mDatas: MutableList = mutableListOf(1,2,3)
mDatas[2]=15
Map同样如此,默认是无法改变元素内容的。如你想改变元素内容,应该使用MutableMap.
var mDatas= mutableMapOf(
Pair("key1","value1"),
Pair("key2","value2"),
Pair("key3","value3")
)
mDatas["key1"]="newValue"
以下我使用了增强型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")
}
对于列表来说,你可能要获取某个索引下的控件,比如如下调用elementAt,但是如果你传入找不到的索引,则会报异常:
var mDatas = listOf(1, 2, 3, 4, 5)
Log.i("IT520",""+mDatas.elementAt(6))
当然,比如我们想找到第一个元素first/最后一个元素last,如果找不到也会直接报异常,如下:
var mDatas2:List = emptyList()
//Log.i("IT520", "" + mDatas2.first())
Log.i("IT520", "" + mDatas2.last())
上面的代码解决起来也比较简单,因为系统还提供了一些可替代的函数,如:elementAtOrElse(如果找不到则给出默认)/elementAtOrNull(如果找不到则返回null)/firstOrNull/lastOrNull等。
再强调次 下面的代码要多敲
以下主要介绍加法plus/减法/minus和取反not,代码如下:
var a: Int = 3
a = a.plus(5)
Log.i("IT520"," $a ")
a = a.minus(2)
Log.i("IT520"," $a ")
var flag:Boolean =false
Log.i("IT520","${flag.not()}")
有时候 我们需要做自增/自减的,代码如下:
var a: Int = 3
a = a.inc() //a++ inc 代表 increase
Log.i("IT520", " $a ")
a = a.dec() //a-- dec 代表 decrease
Log.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 返回的是Boolean
Log.i("IT520", "${3 !in a}")
该关键字也可以用来判断某个字符串中是否存在某个子字符串:
var str = "Hello world !"
Log.i("IT520", "${"Hello" in str}")
三目运算符是我们用的比较的一个技术,这里主要介绍他的替代方案:
Kotlin中,三目运算符很麻烦,但是我们可以使用if语句来代替:
var a: Int = 8
var b: Int = 6
//str = a>b ? "HHH" : "KKK"
var str = if (a > b) "HHH" else "KKK"
在控制流程中的语句中变化最大的属于switch语句,现在改为when了:
var x = 3
when (x) {
1 -> Log.i("IT520","1")
2 -> Log.i("IT520","2")
else -> { // 注意这个语句块
Log.i("IT520","else")
}
}
当case内部是多条代码语句时,可以改写如下:
var x = 3
when (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 = 1
when (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 = 3
when (x) {
in 1..10 -> Log.i("IT520","range 1 to 10")
else -> Log.i("IT520","otherwise")
}
在java开发中,修饰符无非3中,从小到大分别的private,protected,public.而kotlin的修改符达到了4种,多了一个internal。一下介绍他们的用法:
如果你在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()