Kotlin基础(四)Lambda编程
Lambda编程
一、Lambda表达式和成员引用
一)Lambda表达式语法
//注意与Java8中的区别
val sum={ x:Int,y:Int -> x+y }
println(sum(5,6))
run { print(33) }
data class Person(val name:String,val age:Int) fun main(args: Array<String>) {
val persons= listOf<Person>(Person("Tom",3),Person("Jerry",2))
//println(persons.maxBy { it.age }) //不使用任何简明语法的重写
//println(persons.maxBy({p:Person -> p.age})) //如果lambda表达式是函数调用的最后一个实参,可以把它放到括号外面,但只能放一个
//println(persons.maxBy() { p:Person -> p.age }) //lambda为唯一实参时,可以省略小括号
//println(persons.maxBy { p:Person -> p.age }) //如果lambda的参数类型可以被推断出来,可以省略它
//println(persons.maxBy { p -> p.age })
//使用原则:可以先不声明参数类型,观察编译器是否报错 //最简形式:使用默认参数名it代替参数名。如果当前上下文期望的
//是只有一个参数的的lambda且这个参数的类型可以推断出来。
println(persons.maxBy { it.age })
}
fun main(args: Array<String>) {
//与Java不同,Kotlin允许在lambda内部访问非final变量,甚至修改它们
//默认情况下,局部变量的声明周期被限制在声明这个变量的函数中。但是如果
//它被lambda捕捉了,使用这个变量的代码可以被存储并稍后再执行。 fun tryToCountButtonClicks(button:Button):Int{
var count=0
button.onClick {count++}
//这里会始终返回0
return count
}
}
成员引用:
//与Java8一样,如果把函数转换为一个值,你就可以传递它
var getAge=Person :: age //还可以引用顶层函数
run { ::tang } //构造方法引用存储或延期执行创建实例类的动作
val createPerson= ::Person
val p=createPerson("Price",48)
println(p) //引用扩展函数
fun Person.isAdult()= age>=21
val isAdult=Person::isAdult
二)集合的函数式API
1.filter函数:遍历集合并选出应用给定lambda后返回true的那些元素。
val list=listOf(1,2,3,4,5,6)
println(list.filter{it%2==0})
/*[2, 4, 6]*/
2.map函数:对集合中的每一个运用给定函数并把结果收集到一个新集合。
val list= listOf(1,2,3)
println(list.map{it*it})
3.all函数:判断是否所有函数满足判定式
val list= listOf(1,2,3,4,5,6,7)
println(list.all{it>3})//false
4.any函数:检查是否至少存在一个匹配的元素
val list= listOf(1,2,3,4,5,6,7)
println(list.any { it>3 })//true
5.find函数:找到第一满足判定式的元素
val list= listOf(1,2,3,4,5,6,7)
println(list.find { it>3 })//
6.groupBy函数:把列表转换为分组的map
val persons= listOf<Person>(Person("Tom",22), Person("Jimmy",22)
, Person("Jack",33),Person("Blank",33), Person("Price",50))
println(persons.groupBy { it.age })
/*{22=[Person(name=Tom, age=22), Person(name=Jimmy, age=22)],
33=[Person(name=Jack, age=33), Person(name=Blank, age=33)],
50=[Person(name=Price, age=50)]}*/
7.flatMap函数:处理嵌套集合中的元素
val list= listOf<String>("abc","de","fchi")
println(list)//[abc, de, fchi]
println(list.flatMap { it.toList() })
/*[a, b, c, d, e, f, c, h, i]*/
8.flatten函数:只是平铺不做任何变换
9.惰性操作集合:序列
fun main(args: Array<String>) {
val persons= listOf<Person>(Person("Ajax",2), Person("Bob",6),
Person("Tom",5), Person("Auth",3))
persons.map(Person::name).filter { it.startsWith("A") }
persons.map { p:Person ->p.name }.filter { it.startsWith("A") }
/*
* 上面的代码存在的问题:链式调用会创建两个列表,导致效率低下
* 此时可以使用序列
* */ persons.asSequence() //把初始集合转换成序列
.map(Person::name) //序列支持和集合相同的API
.filter { it.startsWith("A") }
.toList() //转换回集合 /*
* 序列操作分为两类:中间和末端。中间操作返回的是另一个序列,
* 末端操作返回的是一个结果,这个结果可能是集合、元素、数字,
* 或者其他从初始集合变换序列中获取的任意对象。
* */
//中间操作始终是惰性的
listOf(1,2,3,4).asSequence()
.map { println("map($it)"); it*it } //没有末端操作不会被执行
.filter { println("filter($it)") ; it%2==0} //没有末端操作不会被执行
}
注意:序列与Java8的Steam的区别:序列不支持在多个CPU上并行执行。
三)使用Java函数式接口
/*Java*/
void post(int delay,Runnable com){}
TestIt().post(1000){ //注意整个程序只会创建一个Runnable实例
println("Run it")
}
fun handle(id : String){ //lambda会捕捉id这个变量
TestIt().post(1000){ println("Run it $id")} //所以每次调用都会创建新的实例
}
SAM构造方法:显示地lambda转换为函数式接口
fun createAllDoneRunnable() :Runnable{
//SAM构造方法名称和函数式接口名称一样,且只接收一个参数
return Runnable { println("All done") }
} //SAM构造方法还可以把从lambda生成的函数接口实例,存储在变量中
val runIt= Runnable { println("Rock & Roll") }
四)带接收者的lambda:with与apply
1.with函数
fun alphabet() :String{
val result=StringBuilder()
for (letter in 'A'..'Z'){
result.append(letter)
}
result.append("\nDone")
return result.toString()
} //用with函数简化
fun alphabe2() : String{
val result=StringBuilder()
//with结构实际上是一个接收两个参数的函数,一个参数
//是result另一个是lambda表达式
return with(result){
for (letter in 'A'..'Z'){
this.append(letter)
}
//可省略this
append("\n Done2")
toString()
}
} //进一步简化
fun alphabet3()= with(StringBuilder()){
for (letter in 'A'..'Z'){
append(letter)
}
append("\n Done3")
toString()
}
2.apply函数
几乎与with函数一样,与with函数的唯一区别是会返回作为实参传递给它的对象(接收者对象)
Kotlin基础(四)Lambda编程的更多相关文章
- Python全栈开发【基础四】
Python全栈开发[基础四] 本节内容: 匿名函数(lambda) 函数式编程(map,filter,reduce) 文件处理 迭代器 三元表达式 列表解析与生成器表达式 生成器 匿名函数 lamb ...
- Python基础:函数式编程
一.概述 Python是一门多范式的编程语言,它同时支持过程式.面向对象和函数式的编程范式.因此,在Python中提供了很多符合 函数式编程 风格的特性和工具. 以下是对 Python中的函数式编程 ...
- Python 基础之socket编程(二)
Python 基础之socket编程(二) 昨天只是对socket编程做了简单的介绍,只是把socket通信的框架搭建起来,要对其中的功能进行进一步的扩充,就来看看今天的料哈! 一.基于tcp的套接字 ...
- python基础之socket编程 (转自林海峰老师)
python基础之socket编程 阅读目录 一 客户端/服务器架构 二 osi七层 三 socket层 四 socket是什么 五 套接字发展史及分类 六 套接字工作流程 七 基于TCP的套接字 ...
- Kotlin基础篇(一)
写在前面: 因为工作需要,目前转安卓开发,用的IDE是AS3.2版本,语言的话,用的是Kotlin.由于之前是做.NET的,没接触过这方面的东西,所以完全是小白一枚.所以想着开个博客,以此来记录自己的 ...
- Java基础-初识面向对象编程(Object-Oriented-Programming)
Java基础-初识面向对象编程(Object-Oriented-Programming) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Java是一门面向对象的程序设计语言.那么什 ...
- Python 基础之socket编程(三)
python 基础之socket编程(三) 前面实现的基于socket通信只能实现什么呢?在tcp协议的通信中就是一个用户说一句,服务端给你回一句,你再给服务端说一句,服务端再给你回一句,就这样一直友 ...
- MySQL基础之事务编程学习笔记
MySQL基础之事务编程学习笔记 在学习<MySQL技术内幕:SQL编程>一书,并做了笔记.本博客内容是自己学了<MySQL技术内幕:SQL编程>事务编程一章之后,根据自己的理 ...
- Spark编程基础_RDD初级编程
摘要:Spark编程基础_RDD初级编程 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素 ...
随机推荐
- Python元组与列表的区别
列表类似于我们用铅笔在纸上写字,写错了还可以擦掉:而元组则类似于用钢笔写字,写错了就擦不掉了,除非换张纸重写. 列表和元组的区别主要体现在一下几个方面: 列表属于可变序列,他的元素可以随时修改或删除: ...
- Python中的函数介绍
调用函数 python中有很多内置函数,我们可以直接调用,内置函数能直接在官网查看:https://docs.python.org/3/library/functions.html#abs 定义函数 ...
- springboot+mybatis+springMVC基础框架搭建
项目结构概览 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http: ...
- 眼底血管分割训练函数(SVM,Adaboost)
# -*- coding: utf-8 -*- import numpy as np from sklearn import svm from sklearn.model_selection impo ...
- 区分TCP包的顺序
确认TCP包的顺序: 使用抓包工具抓包之后,通常按照时间先后排序的,而不是数据的内容逻辑先后.查找内容的先后的关键在于查看TCP中的Sequence number和Acknowledgment num ...
- 蓝桥杯 历届试题 剪格子 dfs
历届试题 剪格子 时间限制:1.0s 内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |10* 1|52| +--****--+ |20 ...
- 011-Python-进程、线程于协程
1.进程与线程 进程: 一个程序要运行时所需的所有资源的集合: 一个进程至少需要一个线程,这个线程称为主线程,一个进程里可以包含多个线程: cpu 核数越多,代表着你可以真正并发的线程越多2个进程之间 ...
- 捷信达会员管理系统SQL语句相关
捷信达会员管理系统SQL语句相关 USE gshis GO SET ANSI_NULLS, QUOTED_IDENTIFIER ON GO /***************************** ...
- webpack学习笔记--区分环境
为什么需要区分环境 在开发网页的时候,一般都会有多套运行环境,例如: 在开发过程中方便开发调试的环境. 发布到线上给用户使用的运行环境. 这两套不同的环境虽然都是由同一套源代码编译而来,但是代码内容却 ...
- CCF-CSP 第三题字符串整理(模拟大法好)
URL映射 规则的相邻两项之间用‘/’分开,所以我们先把所有项分开,然后依次把两个字符串的对应项匹配即可. 分离字符串这里用字符串流(stringstream)处理,先把所有的‘/’变为空格,然后一个 ...