此类文章为houkHan原创,其中知识点阅读与《kotlin从零到精通Android开发》,转载需标明出处,谢谢!
-
基本数据类型
Kotlin声明数据类型以var和val开头,两者的区别是val修饰的变量只能在第一次声明时赋值,后续不能在进行赋值,类似Java李的final关键字,而val修饰的变量在任何时候都可以进行赋值,可以更抽象的理解为val修饰常量,val修饰变量
基本类型名称 | kotlin数据类型 | Java数据类型 | 转换为该类型 |
---|---|---|---|
整型 | Int | int和Integer | toInt |
长整型 | Long | long和Long | toLong |
浮点型 | Float | float和Float | toFloat |
双精度 | Double | double和Double | toDouble |
布尔型 | Boolean | boolean和Boolean | 无 |
字符型 | Char | char | toChar |
字符串 | String | String | toString |
例子:
var a:Int = 1;
var b:Long = 1L
var c:Float = 1F
var d:Boolean = true
-
数组
例子:基本数组类型 名称 初始化 整型数组 IntArray intArrayOf 长整型数组 LongArray longArrayOf 浮点数组 FloatArray floatArrayOf 双精度数组 DoubleArray doubleArrayOf 布尔型数组 BooleanArray booleanArrayOf 字符数组 CharArray charArrayOf
var int_array: IntArray = intArrayOf(1, 2, 3)
var float_array: FloatArray = floatArrayOf(1.0f, 2.0f, 3.0f)
var char_array: CharArray = charArrayOf('a', 'b', 'c')
Kotlin中并没有找到StringArray的数组类型,是因为String是一种特殊的基本数据类型(可以理解为它是一个对象),所以如果想要创建的话需要使用Array<String>类型,也就是把String用<>扩起来,同时分配字符串的方法也变成了arrayOf,下面是声明String类型数组的方法(创建其他对象的数组同理),当然创建以上的数据格式也可以用这种方法
var str_array:Array<String> = arrayOf("hello","world")
var int_array:Array<Int> = arrayOf(1,2,3)
var boolean_array:Array<Boolean> = arrayOf(true,false)
常见的数组元素操作
- 获取长度:java使用的是.length,kotlin使用的是.size
- 获取指定位置的元素:java使用的是方括号加下标的方式来获取,比如int_array[0],kotlin也可以通过此方式来获取,kotlin也有自己的获取方式,get/set,通过get获取值,set设置值。
var str_array:Array<String> = arrayOf("hello","world")
val s = str_array[0]
val g = str_array.get(0)
-
字符串
字符串转换名称 | Kotlin | Java |
---|---|---|
字符串转整型 | toInt | Integer.parseInt |
字符串转长整型 | tolong | Long.parseLong |
字符串转浮点数 | toFloat | Float.parseFloat |
字符串转双精度数 | toDouble | Double.parseDouble |
字符串转布尔型 | toBoolean | Booleean.parseBoolen |
字符串转数组 | toCharArray | toCharArray |
字符串的基本用法中Kotlin和Java所差不大,比如查找字符串、替换字符串、截取字符串、按特定字符分割字符串等,在这方面Kotlin基本兼容了Java的相关方法。对于查找字符串的操作,二者都是用的是replace方法,对于按照特定字符分割字符串的操作两者都是调用split方法。在这些字符串的处理中,唯一的区别是split方法的返回值,在Java中,split返回的是String数组,即String[],但在Kotlin中,split方法的返回值是String队列,即List<String>。同时Kotlin支持通过get获取指定位置的下标。
在字符串的拼接中,Java想把几个变量拼接成字符串,则要么通过加号强行拼接,要么通过String.format函数进行格式化,可前者拼接的加号常常跟数值的加号混在一起,而后者的格式还得开发者死背,例如的%d,%f,%s,%c,%b等格式转换符,实在令人头痛,对于字符串格式这个缺点,Kotlin恰如其分的进行了优化,直接在"$变量名"即可表示在此处引用这个变量。当然如果你想打印$美元符号的话,就不能直接打印它了,因为它属于kotlin的特殊字符,必须经过转义才可以进行打印,在Kotlin中有两种转义的方法。第一种是字符转义,如果你只需要转义一个字符的话可以在字符前面添加反斜杠来完成,即变成"\$",这样一个$就打印出来了,另外一种适合字符串的转义,当然它也可以转义字符,转义的方法是使用${'***'}表达式,改表达式外层${''}是转义声明,内层的***则为需要转义的内容,所以可以通过${'$'}来完成一个$符号的打印。
var str_hello:String = "Hello"
var str_world:String = "$str_hello World"//Hello World
var s:String = "\$ $str_hello World"//$ Hello World
var f:String = "${'$'} $str_hello World"//$ Hello World
-
容器
首先,Kotlin号称是全面兼容Java的,那么在Java中的容器类仍可以在Kotlin中使用,包括大家熟悉的Set,ArrayList,HashMap等。不过Kotlin作为一门新生的语言,当然也有自己的容器类,与Java类似,Kotlin的容器类也大致分为集合Set,队列List,映射Map,与Java不同的是Kotlin对每个容器类型进行了分类:只读与可变两种类型,这里区分的标准是该容器是否可以进行增、删、改等变更操作。Kotlin对变量的修改操作很慎重,每个变量在自定义的时候就必须指定是否可以修改,比如开头所说的val和var,val表示变量在初始化赋值后不可修改,添加var修饰则表示变量可以修改。至于容器则默认为只读容器,如果需要允许修改容器变量,Kotlin就需要加上Mutable(可变的)前缀形成新的容器,比如MutableSet表示可变集合,MutableList表示可变队列,MutableMap表示可变映射,只有可变的容器才可以对内部的元素进行增、删、改操作。
既然集合Set、队列List、映射Map三者都是容器,那么他们必定拥有相同的容器方法,这些具体的公共方法如下。
- isEmppty:判断容器是否为空。
- isNoEmpty:判断容器是否非空。
- clear:清空该容器。
- contains:判断该容器是否包含指定元素。
- iterator:判断该容器的迭代器。
- count:判断该容器的元素个数,也可以通过size属性获取元素的数量。
另外Kotlin是允许在声明容器的时候就进行初始化赋值,如同对数组进行初始化那样。而Java是无法在容器声明的时候为其赋值的,由此可以Kotlin的这点给开发者带来了很大的便利,下面是一个List初始化的代码例子:
val list:List<String> = listOf("北京","上海","广州","深圳")
当然不同容器也有不同的初始化方法,详见下表:
Kotlin容器 | 容器名称 | 初始化方法 |
---|---|---|
只读集合 | Set | setOf |
可变集合 | MutableSet | mutableSetOf |
只读队列 | List | listOf |
可变队列 | MutableList | mutableListOf |
只读映射 | Map | mapOf |
可变映射 | MutableMap | mutableMapOf |
接下来分别介绍一下这六种容器的详细使用
-
集合Set/MutableSet
集合是一种最简单的容器,它具有以下特点:
- 容器内部是不按照顺序排列的,因此无法按照下标访问
- 容器内部元素存在唯一性,通过哈希值校验是否存在一样的元素,若存在,则将其覆盖。
因为Set是只读集合,初始化赋值后便不可更改,所以元素元素变更的方法只适用于可变集合MutableSet,但Mutable的变更操作尚有以下限制:
- MutableSet的add方法仅仅往集合中添加元素,由于集合是无序的,因此无法知道添加到的具体位置
- MutableSet的remove方法用于删除指定元素,由于集合是无序的,因此无法删除指定位置的元素
- MutableSet没有修改元素的方法,一个元素一旦添加,就不可修改。
对于集合的遍历操作,Kotlin提供了好几种方式,又熟悉的for-in循环、迭代器遍历、还有新面孔forEach便利,这三种集合遍历方式如下。
- for-in循环
fun setForIn() { val mSet: Set<String> = setOf("北京", "上海", "广州", "深圳") for (item in mSet) { print(item+"\n") } }
- 迭代器遍历
fun setIterator(){ val mSet: Set<String> = setOf("北京", "上海", "广州", "深圳") val iterator = mSet.iterator() while(iterator.hasNext()){ print(iterator.next()+"\n") } }
- forEach遍历
fun setForEach() { val mSet: Set<String> = setOf("北京", "上海", "广州", "深圳") //不指定的话通过it获取元素 mSet.forEach { print(it + "\n") } print("-------\n") //可以通过一下方式指定 mSet.forEach { item -> print(item + "\n") } }
结合以上有关Set/MutableSet的用法说明,可以发现集合在实战中有诸多不足,主要体现在以下几点:
- 集合不允许修改内部元素的值
- 集合无法删除指定位置的元素
- 不能通过下标来获取指定位置的元素
鉴于以上缺点,故在实际开发中除了特殊情况以外基本不用集合Set/MutableSet,大多数情况下使用他的两个兄弟--队列List/MutableList和映射Map/MutableMap
-
队列List/MutableList
队列是一种元素之间按照顺序排列的容器,内部的元素是可以重复的,它与集合最大的区别在于多了次序管理,正因为如此,他比集合多提供了以下功能:
- 队列可以通过get来获取到指定元素的下标,同时也可以通过下标来获取指定位置的元素
- MutableList的add方法每次都默认吧元素添加到末尾,也可以指定添加的位置
- MutableList的set方法允许替换和修改指定位置的元素
- MutableList的remove方法允许删除指定位置的元素
- 队列除了拥有跟集合一样的三种遍历方式(for-in循环,迭代器遍历,forEach遍历)以外,还多了一种按照下标循环遍历的方式,具体实现如下:
fun listFor(){ val mList:List<String> = listOf("北京", "上海", "广州", "深圳") for (index in mList.indices){ print(mList[index]+"\n") } }
- MutableList提供了sort系列的方法用于给队列中的元素重新排序,其中sortBy方法表示按照指定条件升序排列,sortByDescending表示按照指定条件降序排列,在这里就不多赘述了,如有需要,请自行百度
-
映射Map/MutableMap
映射内部保存的是一组键值对(Key-Value),也就是说每个元素都有两部分组成,第一部分是元素的键,相当于元素的名字;第二部分是元素的值,存放着元素的详细信息。元素的键与值是一一对应的关系,相同的键名指向的键值是唯一的,所以映射中那个元素的键名各不相同(Key值唯一),这个特性使得映射的变更操作与队列有以下不同之处:
- 映射的containsKey方法来判断是否存在指定键名的元素(Key),containsValue方法来判断是否存在指定键值的元素(Value)
- MutableMap的put方法不是单单的添加元素,而是只能的数据存储。每次调用put方法时,映射会根据键名(key)来寻找同名元素,如果找不到就添加新元素,如果找得到就用新元素替换旧元素的键值(Value)
- MutableMap的remove方法是通过键名(Key)来删除元素的
- 调用mapOf和mutableMapOf方法初始化映射时,有两种方法来表达耽搁元素对应的元素(Key对应的Value),其一是通过“键名(Key) to 键值(Value)”的形式,其二是采取Pair配对方式,形如“Pair(键名(Key),键值(Value))”,下面是代码实例:
val mMapOf: Map<String, String> = mapOf("河北" to "石家庄", "山西" to "太原", "河南" to "郑州", "山东" to "济南")
val mMapPair: Map<String, String> = mapOf(Pair("河北", "石家庄"), Pair("山西", "太原"), Pair("河南", "郑州"), Pair("山东", "济南"))
映射的遍历与集合类似,也有for-in循环,迭代器遍历,forEach遍历三种方式,但是由于映射的元素是一一对应的,因此它的遍历方式可能稍有不同,详细如下:
//Map for-in循环
fun mapForIn() {
val mMapOf: Map<String, String> = mapOf("河北" to "石家庄", "山西" to "太原", "河南" to "郑州", "山东" to "济南")
for (item in mMapOf) {
print(item.key + "---" + item.value + "\n")
}
}
//Map 迭代器遍历
fun mapIterator() {
val mMapOf: Map<String, String> = mapOf("河北" to "石家庄", "山西" to "太原", "河南" to "郑州", "山东" to "济南")
val iterator = mMapOf.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
print(item.key + "---" + item.value + "\n")
}
}
//Map for-Each
fun mapForEach() {
val mMapOf: Map<String, String> = mapOf("河北" to "石家庄", "山西" to "太原", "河南" to "郑州", "山东" to "济南")
mMapOf.forEach { print("${it.key}---${it.value}\n") }
print("-------\n")
mMapOf.forEach { (key, value) -> print("$key---$value\n") }
print("-------\n")
mMapOf.forEach { item -> print("${item.key}---${item.value}\n") }
}