常见的高阶函数
// 当高阶函数是最后一个的时候,可以下列的格式
// 一个参数的时候,该参数是`it`
intArray.forEach(){
}
斐波拉契计算时间
fun main() {
cost {
val fibNext = fibonacci()
for (i in 0..10) {
println(fibNext())
}
}
}
fun cost(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
println("time ${System.currentTimeMillis() - start}")
}
fun fibonacci(): () -> Long {
// 写在这里的东西看出一个类的属性
var first = 0L;
var second = 1L;
// 这里整体是一个函数返回值
// return 代表这个类的invoke
return {
val next = first + second
val current = first;
first = second
second = next
current
}
}
// 以下是java源码
@NotNull
public static final Function0 fibonacci() {
final LongRef first = new LongRef();
first.element = 0L;
final LongRef second = new LongRef();
second.element = 1L;
return (Function0)(new Function0() {
// $FF: synthetic method
// $FF: bridge method
public Object invoke() {
return this.invoke();
}
public final long invoke() {
long next = first.element + second.element;
long current = first.element;
first.element = second.element;
second.element = next;
return current;
}
});
}
// 函数类型其实也是类. 他可以保留状态. 返回值就是invoke的符号重载
内联函数
关键字
inline
高阶函数和内敛更配,因为高阶函数本质是一个类
所以使用内敛函数,减少了类创建的开销
内敛高阶函数的return
val ints = intArrayOf(1, 2, 3, 4)
ints.forEach {
if (it == 3)
return@forEach// 相当于continue return 就直接退出
println("Hello $it")
}
non-local return
inline fun Runnable(crossinline block: () -> Unit):Runnable {
return object : Runnable {
override fun run() {
block()
}
}
}
几个有用的函数
函数名 | 介绍 | 推荐指数 |
---|---|---|
let | val r= X.let{x->R} |
*** |
run | val r= X.run{this: x->R} |
* |
also | val x=X.also(x->Unit) | *** |
apply | val x =X.apply{this:X->Unit} | * |
use | val r=Closeable.use{c->R} | *** |
集合的映射操作举例
函数名 | 说明 |
---|---|
filter | 保留满足条件的原始 |
map | 所有原始银蛇其他元素构成新的集合 |
flatMap | 映射新集合并合并这些集合得到新集合 |
SAM
Single Abstract Method: 一个抽象方法
一个参数类型为只有一个方法的Java接口的Java调用时可用Lambda表达式做转换作为参数
executor.submit{
println("run in executor.")
}
// 下列Kt
object:Runnable{
fun run(){
......
}
}
object:Runnable{
....
}
//Java 可以
Lesson01Kt.submit(new Invokable() {
@Override
public void invoke() {
}
});
Lesson01Kt.submit(() -> {
});
//Kt 不可以
fun main() {
// 所谓的不可以的解决方法,只能使用下列这种匿名内部类的方式
// 正确的写法
submit(object : Invokable {
override fun invoke() {
}
})
// 错误的写法:不支持SAM. 因为 Kt有函数类型
// submit{
// ....
// }
// 这里就可以SAM: 调用Java的接口. 为了兼容Java代码表
submitRunnable {
}
// 这个是kt规范的写法,使用函数类型
submit {
}
}
fun submit(f: () -> Unit) {
}
//修改别名
typealias FunctionX = () -> Unit
fun submit2(f: Function0<Unit>) {
}
fun submit3(f: FunctionX) {
}
fun submitRunnable(runnable: Runnable) {
runnable.run()
}
fun submit(invoker: Invokable) {
invoker.invoke()
}
interface Invokable {
fun invoke();
}
高阶字符的个数
File("build.gradle.kts")
.readText()
.toCharArray()
.filterNot { it.isWhitespace() }
.groupBy {
it
}.map {
it.key to it.value.size
}.let {
println(it)
}
手写一个Html的DSL
import com.bennyhuo.kotlin.advancedfunctions.eg.body
import com.bennyhuo.kotlin.advancedfunctions.eg.head
import java.io.File
import java.lang.RuntimeException
fun main(args: Array<String>) {
val htmlContent = com.bennyhuo.kotlin.advancedfunctions.eg.html {
head {
"meta" { "charset"("UTF-8") }
}
body {
"div" {
"style"(
"""
width: 200px;
height: 200px;
line-height: 200px;
background-color: #C9394A;
text-align: center
""".trimIndent()
)
"span" {
"style"(
"""
color: white;
font-family: Microsoft YaHei
""".trimIndent()
)
+"Hello HTML DSL!!"
}
}
}
}.render()
File("Kotlin2.html").writeText(htmlContent)
}
interface Node {
fun render(): String
}
class StringNode(val content: String) : Node {
override fun render(): String {
return content
}
}
class BlockNode(val name: String) : Node {
val children = ArrayList<Node>();
val properties = HashMap<String, Any>()
override fun render(): String {
return """
<$name ${properties.map { "${it.key}='${it.value}'" }.joinToString(" ")}>
${children.joinToString(" ") { it.render() }}
</$name>
""".trimIndent()
}
operator fun String.invoke(block: BlockNode.() -> Unit): BlockNode {
val node = BlockNode(this)
node.block()
this@BlockNode.children += node
return node;
}
operator fun String.invoke(value: Any) {
properties[this] = value
}
operator fun String.unaryPlus() {
children += StringNode(this)
}
}
fun html(block: BlockNode.() -> Unit): BlockNode {
val tagHtml = BlockNode("html");
tagHtml.block();
return tagHtml
}
fun BlockNode.head(block: BlockNode.() -> Unit): BlockNode {
if (this.name != "html") {
throw RuntimeException("parent is not html tag")
}
val head = BlockNode("head")
head.block()
this.children += head
return head
}
fun BlockNode.body(block: BlockNode.() -> Unit): BlockNode {
if (this.name != "html") {
throw RuntimeException("parent is not html tag")
}
val head = BlockNode("head")
head.block()
this.children += head
return head
}
将一个groovy 变成 Kotlin DSL
修改文件名字
将setting.gradle
-->setting.gradle.kts
在kts 中字符串是
双引号
rootProject.name = 'untitled1'-->
rootProject.name = "untitled1"
3.再次修改文件名字
将'build.gradle'-->'build.gradle.kts'
- 修改build.gradle.kts
4.1
plugins{
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.3.41'
}
变成
plugins {
kotlin("jvm") version "1.4.32"
}
// 增加(), 单引号变成双引号
group 'me.v_daoszhong'
version '1.0-SNAPSHOT'
变成
group = "me.v_daoszhong"
version = "1.0-SNAPSHOT"