1、Lambda
lambda 表达式总是括在花括号中, 完整语法形式的参数声明放在花括号内,并有可选的类型标注, 函数体跟在一个 -> 符号之后。如果推断出的该 lambda 的返回类型不是 Unit,那么该 lambda 主体中的最后一个(或可能是单个) 表达式会视为返回值。
//Lambda表达式的完整语法形式:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
//函数的最后一个参数是函数,作为参数传入的lambda表达式可以放在圆括号外
val product = items.fold(1) { acc, e -> acc * e }
//若lambda表达式是调用时唯一的参数,则圆括号可以省略
val maxLengthFruit = list.maxBy { fruit : String -> fruit.length }
val maxLengthFruit = list.maxBy { fruit -> fruit.length }
//lambda表达式只有一个参数时可以用it隐式代替
val maxLengthFruit = list.maxBy { it.length }
2、标准函数
also、 let、 apply、 run、 with
上下文对象:
this:run、 with、 apply,通过关键字this引用上下文对象,在它们的 lambda 表达式中可以像在普通的类函数中一样访问上下文对象,大多数场景下当访问接收者对象时可以省略this。
it:let、also,将上下文对象作为lambda的参数,默认名称为it,当调用对象函数或属性时不能想this一样隐式访问对象。
返回值:
apply、 also返回上下文对象
let、 run、 with返回lambda表达式结果
3、扩展函数
在不修改某个类的源码的情况下,向该类添加新的函数为一个类添加一个新的函数或属性
//定义函数时在函数名前加要扩展的类名 ClassName.methodName()
fun String.lettersCount(): Int {
var count = 0
for(char in this){
if(char.isLetter()) {
count++
}
}
return count
}
val num = "asfbHUHFhfHh@#".lettersCount()
4、高阶函数
函数类型:(String, Int)-> Unit
参数有“函数类型”或者返回值是“函数类型”的函数
fun example( func : ( String,Int) -> Unit ) {
func(“hello”,1232)
}
5、集合的函数式API
map():映射
val list = listOf("Apple","Banana","Orange","Pear","Grape","Watermelon")
val newlist = list.map { it.toUpperCase() }
for(fruit in newlist){
println(fruit)//全大写
}
collect()
是流(Stream)对象的一个终端操作符,用于将流中的元素收集到一个集合或其他数据结构中
List<String> words = Arrays.asList("apple", "banana", "orange");
Set<String> collectedSet = words.stream()
.collect(Collectors.toSet());
Collectors.toSet()
Collectors.toList()等
maxBy():找出长度最长的单词
val list = listOf("Apple","Banana","Orange","Pear","Grape","Watermelon")
var maxLengthFruit = list.maxBy { it.length }
println("max lenth fruit is "+maxLengthFruit)
filter():函数就是过滤集合中数据的,可以单独使用,也可以配合 map 函数使用
val list = listOf("Apple","Banana","Orange","Watermelon")
val newlist = list.filter { it.length <=5 }
.map { it.toUpperCase() }
for(fruit in newlist){
println(fruit)
}
slice():取集合中的一些元素创建新的集合
val numberList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
val newNumberList1 = numberList.slice(IntRange(3, 6))
newNumberList1.forEach {
print("$it ") //打印结果:4 5 6 7
}
val newNumberList2 = numberList.slice(listOf(1, 3, 7))
newNumberList2.forEach {
print("$it ") //打印结果:2 4 8
}
take():从第一项开始取n个元素组成新的集合
takeLast():从最后一项开始取n个元素组成新的集合
takeWhile() :从第一项开始取满足条件的项组成新的集合
takeLastWhile():
val numberList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
val newNumberList1 = numberList.take(3)
newNumberList1.forEach {
print("$it ") //打印结果:1 2 3
}
val strList = listOf("java", "javaScript", "kotlin", "C++", "javaFx", "python", "Swift")
strList.takeWhile{ it.startsWith("java") }.forEach { print("$it ") }
//java javaScript
drop(n) :从第一项删除n个元素
dropLast(n):从最后一项删除n个元素
dropWhile():从第一项删除满足条件的元素,直到遇到第一个不满足条件的为止
dropLastWhile():
val numberList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
numberList.drop(5).forEach { print("$it ") }//6 7 8 9
val strList = listOf("java", "javaScript", "kotlin", "C++", "javaFx", "python", "Swift")
strList.dropWhile { it.startsWith("java") }.forEach { print("$it ") }
//kotlin C++ javaFx python
distinct():去除集合中的重复元素
distinctBy():根据操作后的几个去除重复元素
val numberList = listOf(1, 1 , 2, 3, 4, 4, 6, 7, 8, 8)
numList.distinct()//1 2 3 4 6 7 8
numList.distinctBy {
it + 1
}//2 3 4 5 7 8 9
any 函数用于判断集合中是否至少存在一个元素满足指定条件,返回True/False
val list = listOf("Apple", "Banana", "Orange", "Watermelon")
val anyResult = list.any { it.length <= 5 }
all 函数用于判断集合中是否所有元素满足指定条件,返回True/False
val list = listOf("Apple", "Banana", "Orange", "Watermelon")
val allResult = list.all { it.length <= 5 }
count():返回集合中的元素个数/返回集合中满足条件的元素个数
val strList = listOf("java", "javaScript", "kotlin", "C++", "javaFx", "python", "Swift")
strList.count{ it.startsWith("java") }//3
None():如果集合为空返回True/如果集合中没有满足条件的元素返回True
val strList = listOf("java", "javaScript", "kotlin", "C++", "javaFx", "python", "Swift")
strList.None{ it.startsWith("java") }//False
reduce与fold函数:将所提供的操作应用于集合元素并返回累积的结果,reduce的第一步则将第一个和第二个元素作为第一步的操作参数,fold提供一个初始值并将其作为第一步的累积值
val listFold = listOf("hello", "1", "2", "3", "4").fold("初始值") {
acc, nextElement -> acc + nextElement
}//初始值hello1234
val listReduce :String = listOf("hello", "1", "2", "3", "4").reduce {
acc, str -> acc + str
}//hello1234
plus():集合合并
val list1 = listOf("Apple", "Banana")
val list2 = listOf("Orange", "Watermelon")
val allResult = list1.plus{ list2 }//
6、java函数式api
先决条件:kotin代码中调研java方法,且该方法接收一个java单抽象方法接口参数(java单抽象方法接口指接口中只有一个待实现方法)
new Thread(new Runnable() {
@Override
public void run() {
...
}
}).start();
Thread(object : Runnable {
override fun run() {
...
}
}).start()
Thread(Runnable {
...
}).start()
Thread {
...
}.start()
7、监听器
不通过新建接口类的方法实现,高阶函数
class Test(var listener:(value:Int) -> Unit) {
var callBack: (result: String) -> Unit = {
}
}
val test = Test {
value -> ...//对value进行处理
callBack = ...//对result值处理
}
8、liveData
一种观察者模式
val testLiveData = MutableLiveData<String>()
testLiveData.value = "..."
testLiveData.observe(this) {
//对String进行处理
}
import com.jeremyliao.liveeventbus.LiveEventBus
const val EVENT_RESULT = "EVENT_RESULT"
LiveEventBus.get<Pair<Result?, String>>(EVENT_RESULT).post(data to request)//Result:自定义的数据结构类型
LiveEventBus.get<Pair<Result?, String>>(EVENT_RESULT).observe(this) {
it.first
it.second
}
9、协程
Kotlin 协程是一种用于简化异步编程的并发框架。它提供了顺序编写异步代码的能力,简化了线程切换和异常处理,并提供了作用域和取消的机制,使得异步编程更加容易、高效和可靠
runBlocking{…}:创建协程作用域。
MainScope:一个特殊的协程作用域,与主线程的生命周期相关。
viewModelScope.launch:和ViewModel组件生命周期相同
GlobalScope.launch:一个顶层的协程作用域对象,是一个单例对象,和整个应用程序的生命周期相同。
launch:协程启动函数
Dispatchers:协程中用于调度协程执行的调度器的工具类,调度器定义了协程在哪个线程或线程池上执行,Dispatchers.Default——默认调度器,CPU密集型任务;Dispatchers.IO——IO密集型任务;Dispatchers.Main——安卓主线程上执行任务。
withContext():用于切换协程上下文的函数,协程上下文包含了协程运行所需的执行环境,例如线程或调度器。
suspend:函数修饰符,用于标记挂起函数,挂起函数是可以在协程中使用的特殊函数,它可以暂停当前协程的执行,而不会阻塞线程。当一个协程调用一个挂起函数时,它会将控制权交给调用者,并在挂起函数执行完毕后恢复执行。
suspend fun FetchData(): String {
delay(1000)
return "Data from network"
}
suspend fun ProcessData(data: String): String {
delay(2000)
return "Processed data: $data"
}
fun main() {
runBlocking {
launch(Dispatchers.Default) {
val fetchedData = FetchData()
// 切换到 IO 调度器执行耗时的处理操作
val processedData = withContext(Dispatchers.IO) {
processData(fetchedData)
}
// 切换回默认调度器打印结果
withContext(Dispatchers.Default) {
println(processedData)
}
}
println("Main thread continues")
}
}
10、lazy
用来延迟初始化属性,直到我们第一次使用该属性时才进行实际的初始化操作。
val propertyName: Type by lazy {
// 初始化代码块
// 返回属性的值
}
by lazy是线程安全的适用于多线程,他的值只会被初始化一次,只适用于不可变属性(val),lazy是一个局部函数,它存储了一个线程安全的 Lazy 实例,负责保存属性的初始化状态和值,在需要时进行初始化。
lazy可带参数:
val propertyName: Type by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
// 初始化代码块
// 返回属性的值
}
LazyThreadSafetyMode.SYNCHRONIZED: 使用同步锁来保证线程安全。
LazyThreadSafetyMode.PUBLICATION: 在多线程环境中可能有多个线程同时执行初始化,但只有第一个执行完成的结果会被返回,其他线程会使用这个结果。
LazyThreadSafetyMode.NONE: 不保证线程安全性,适用于单线程环境。如果在多线程环境下使用此模式,可能会导致不确定的行为
initializer: () -> T: 这是 lazy 函数最常用的参数,用于指定属性的初始化操作。它是一个 lambda 表达式,返回属性的初始值。例如:
val propertyName: Type by lazy {
// 初始化代码块
// 返回属性的值
}
onUndecided: (T) -> Unit: 这个参数是一个 lambda 表达式,在属性的值尚未初始化时被调用。它接收一个参数,即属性的类型,并在属性的值尚未初始化时执行操作。例如:
val propertyName: Type by lazy(onUndecided = { uninitializedValue ->
// 处理属性未初始化的情况
}) {
// 初始化代码块
// 返回属性的值
}