Kotlin学习 - 集合+Lambda表达式

本文介绍了Kotlin中的集合类型,包括不可变集合和可变集合的创建与操作,如List的读取、遍历和去重,以及Map和Set的使用。同时,讲解了集合之间的类型转换,并展示了如何利用函数式编程API如maxByOrNull、map和filter进行数据处理。此外,文章还强调了安全访问集合元素的方法,以避免ArrayIndexOutOfBoundsException。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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或者getOrNullgetOrElse传入索引和出错后返回的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 - anyall

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

本文参考书籍:《第一行代码》- 郭霖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值