List集合
Kotlin集合分为可变集合和不可变集合,不可变的集合指的就是该集合只能用于读取,无法进行添加、修改或删除操作。
1、不可变集合
val fruits = listOf<String>("apple","orange","pear")
2、可变集合
fun main() {
val names = mutableListOf("Tom", "Lucky", "Daniel")
names.add("Alice")
names+= "Sara"
for (name in names){
print("$name - ")
}
}
3、集合类型转换
不可变集合转可变集合toMutableList()
fun main() {
val fruits = listOf("apple", "orange", "pear")
val newFruits = fruits.toMutableList()
newFruits.add("kiwi")
println(fruits)
println(newFruits)
}
//运行结果:
[apple, orange, pear]
[apple, orange, pear, kiwi]
可变集合转不可变集合:toList()
fun main() {
val names = mutableListOf("Tom", "Lucky", "Daniel")
val newNames = names.toList()
names.add("Alice")
println(names)
println(newNames)
}
//运行结果:
[Tom, Lucky, Daniel, Alice]
[Tom, Lucky, Daniel]
注意调用转换集合类型函数会生成一个新的集合对象,原来的类型不受影响。
4、集合元素读取
fun main() {
val fruits = listOf("apple", "orange", "pear")
println(fruits.get(2))//Should be replaced with indexing
println(fruits[2])
}
元素读取有两种方式,一种是和Java一样使用get
,但是Kotlin编译器会提示:Should be replaced with indexing,提倡使用像Java中数组一样加中括号和索引读取元素。
fun main() {
val fruits = listOf("apple", "orange", "pear")
println(fruits[5])
}
在使用索引读取元素的时候,很容易出现数组越界的风险,例如上面代码报错:越界ArrayIndexOutOfBoundsException。
解决越界,可以使用安全索引取值方法: getOrElse
或者getOrNull
。 getOrElse
传入索引和出错后返回的Lambda表达式,getOrNull
传入索引,找不到返回是null
。
fun main() {
val fruits = listOf("apple", "orange", "pear")
println(fruits.getOrElse(4) {
"IndexOutOfBounds"
})
println(fruits.getOrNull(4))
println(fruits.getOrNull(4) ?: "IndexOutOfBounds")
}
5、集合元素遍历
fun main() {
val names = mutableListOf("Tom", "Lucky", "Daniel")
for (name in names){
print("$name - ")
}
println()
names.forEach{
print("$it * ")
}
println()
//遍历同时获取索引
names.forEachIndexed{
index,item ->
print("$index-$item & ")
}
}
运行结果:
Tom - Lucky - Daniel -
Tom * Lucky * Daniel *
0-Tom & 1-Lucky & 2-Daniel &
Map集合
1、不可变集合
val fruits = mapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
这里key
值和value
是通过to
进行连接,但是to
并不是关键字,而是一个infix
函数。
2、可变集合
fun main() {
//初始化方式一
var fruits = mutableMapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
//初始化方式二
var fruitList = mutableMapOf(Pair("apple",2.5) ,Pair("orange",5),Pair("pear",3))
//添加元素
fruits.put("kiwi",6)//不推荐
fruits["banana"] = 5//推荐
fruits += "watermelon" to 10
for ((key, value) in fruits){
println("$key's price is $value")
}
}
3、集合类型转换
fun main() {
val fruits = mapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
val newFruits = fruits.toMutableMap()
newFruits.put("kiwi",6)
println(newFruits)
var fruits = mutableMapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
println(fruits.toMap())
}
4、集合元素读取
fun main() {
val fruits = mapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
println(fruits["apple"])
println(fruits.getValue("apple"))
println(fruits.getOrElse("banana") {
"banana has not price" })
println(fruits.getOrDefault("banana", 0))
}
//运行结果
2.5
2.5
banana has not price
0
5、集合元素遍历
fun main() {
val fruits = mapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
fruits.forEach {
println("${
it.key} + ${
it.value} ")
}
}
//运行结果:
apple + 2.5
orange + 5
pear + 3
Set集合
1、不可变集合
val set = setOf("apple", "orange", "pear", "pear")
2、可变集合
val mutableSet = mutableSetOf("apple", "orange", "pear", "pear")
3、集合类型转换
fun main() {
val set = setOf("apple", "orange", "pear", "pear")
val newSet = set.toMutableSet();
newSet.add("banana")
newSet += "kiwi"
//添加元素
println(newSet)
val mutableSet = mutableSetOf("apple", "orange", "pear", "pear")
println(mutableSet.toSet())
}
4、集合元素读取
fun main() {
val set = setOf("apple", "orange", "pear", "pear")
println(set.elementAt(1))
}
//运行结果:orange
5、集合元素遍历
fun main() {
val set = setOf("apple", "orange", "pear", "pear")
set.forEach{
print("$it ")
}
}
//运行结果
apple orange pear
注意:Set和List相比有个特点就是集合数据均不相同,都是唯一的,所以上面例子打印出来只有一个"pear"
。
List去重的两种方式:
fun main() {
val list = listOf("apple", "orange", "pear", "pear")
//去重方式1
val newList = list.toSet().toList()
println(list)
println(newList)
//去重方式2 快捷函数distinct
val newList1 = list.distinct()
println(list)
println(newList1)
}
//运行结果
[apple, orange, pear, pear]
[apple, orange, pear]
[apple, orange, pear, pear]
[apple, orange, pear]
上面在添加元素的时候有的用了运算符,看不懂的小伙伴可以去看下另一篇文章Kotlin学习 - 运算符重载
集合的函数式API
API - maxByOrNull
这里有个需求找到上面列表中水果名字最长的水果:
fun main() {
val fruits = listOf<String>("apple", "orange", "pear", "watermelon")
val maxLengthFruit = fruits.maxByOrNull {
it.length }
println(maxLengthFruit)
}
//运行结果:watermelon
这里用到的maxByOrNull
就是集合的函数式API,作用是根据大括号中Lambda表达式筛选出符合条件最大的。
1、Lambda表达式使用
Lambda语法结构:
{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
maxByOrNull
函数需要一个Lambda表达式,最初的写法如下:
val lambda = {
fruit: String -> fruit.length }
val maxLengthFruit = fruits.maxByOrNull(lambda )
2、Lambda表达式简化写法
在很多情况下,我们并不需要使用Lambda 表达式完整的语法结构,而是有很多种简化的写法。
1)直接把Lambda表达式传入到函数中,不在单独声明:
val maxLengthFruit = fruits.maxByOrNull({
fruit: String -> fruit.length })
2)当Lambda 参数是函数的最后一个参数时,可以将Lambda 表达式移到函数括号的外面:
val maxLengthFruit = fruits.maxByOrNull(){
fruit: String -> fruit.length }
3)如果Lambda 参数是函数的唯一一个参数的话,还可以将函数的括号省略
val maxLengthFruit = fruits.maxByOrNull{
fruit: String -> fruit.length }
4)因为Kotlin拥有出色的类型推导机制,所以入参类型可以去掉:
val maxLengthFruit = fruits.maxByOrNull{
fruit -> fruit.length }
5)当Lambda 表达式的参数列表中只有一个参数时,也不必声明参数名,而是可以使用it
关键字来代替:
val maxLengthFruit = fruits.maxByOrNull {
it.length }
经过上面一系列的变化最后得到了刚开始写的语句。
3、练习:模仿上面例子可以写一个筛选出水果中价格最大的水果:
fun main() {
var fruitsMap = mutableMapOf("apple" to 2.5, "orange" to 5, "pear" to 3)
val maxPriceFruit = fruitsMap.maxByOrNull {
it.value.toFloat() }
println(maxPriceFruit?.key)
}
//运行结果:orange
API - map
API map
将集合中的每个元素都映射成一个另外的值,映射的规则在Lambda 表达式中指定,最终生成一个新的集合。
fun main() {
val fruits = listOf<String>("apple", "orange", "pear", "watermelon")
val newFruitList = fruits.map {
it.uppercase() }
println(newFruitList)
}
//[APPLE, ORANGE, PEAR, WATERMELON]
API - filter
filter
函数是用来过滤集合中的数据的,它可以单独使用,也可以配合map
函数一起使用。
需求:将水果名字长度大于5的水果转为大写
fun main() {
val fruits = listOf<String>("apple", "orange", "pear", "watermelon")
val newFruitList = fruits.filter {
it.length > 5 }.map {
it.uppercase() }
println(newFruitList)
}
//[ORANGE, WATERMELON]
API - any
和all
any
函数用于判断集合中是否至少存在一个元素满足指定条件,all
函数用于判断集合中是否所有元素都满足指定条件。
fun main() {
val fruits = listOf<String>("apple", "orange", "pear", "watermelon")
val anyResult = fruits.any {
it.length > 5 }
val allResult = fruits.all {
it.length > 5 }
println("anyResult: $anyResult | allResult: $allResult")
}
//anyResult: true | allResult: false
本文参考书籍:《第一行代码》- 郭霖