kotlin的重新学习--05高阶函数

常见的高阶函数

// 当高阶函数是最后一个的时候,可以下列的格式
// 一个参数的时候,该参数是`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

  1. 修改文件名字
    setting.gradle--> setting.gradle.kts

  2. 在kts 中字符串是双引号
    rootProject.name = 'untitled1'-->
    rootProject.name = "untitled1"

3.再次修改文件名字
将'build.gradle'-->'build.gradle.kts'

  1. 修改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"







最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容