Kotlin的高阶函数与泛型

来一个demo:带返回函数的函数

data class Person (
    val firstName :String,
    val lastName :String,
    val phoneNumber:String?

)

class ContactListFilters{
var prefix:String=""
var onlyWithNumber:Boolean=false
fun getPredicate():(Person) -> Boolean{
    val startsWithPrefix={
        p: Person ->
        p.firstName.startsWith(prefix)||p.lastName.startsWith(prefix)
    }
    if (!onlyWithNumber){
        return startsWithPrefix
    }
    return {
        startsWithPrefix(it) && it.phoneNumber!=null
    }
}
}

fun main(args: Array<String>) {
val contacts= listOf(Person("dsfd","ddfs","112233"),
        Person("kjk","wqrre","65644"),
        Person("awqq","pioi",null)
        )

val contactListFilters=ContactListFilters()
with(contactListFilters){
    prefix="kj"
    onlyWithNumber=true
}

println(contacts.filter(
        contactListFilters.getPredicate()
))
}

Lambda筛选demo

/**
 *
 * @author ll
 * @Description:记录站点数据
 * @date Created in 2018/04/07 09:55 AM
 */
data class SiteVisit (
    val path:String,//路径
    val duration:Double,//访问时长
    val os:OS //系统
)

enum class OS{
WINDOWS,LINUX,MAC,IOS,ANDROID
}

计算Windows时间

 val log= listOf(
        SiteVisit("/",34.0,OS.WINDOWS),
        SiteVisit("/dfdf",22.0,OS.MAC),
        SiteVisit("/dfgg",12.0,OS.WINDOWS),
        SiteVisit("/ryyy",8.0,OS.IOS),
        SiteVisit("/wtyty",16.3,OS.ANDROID)
)

//Windows平均访问时间
val avgWindows=log
        .filter { it.os==OS.WINDOWS }
        .map (SiteVisit::duration )
        .average()

println(avgWindows)

抽取公共函数:

fun List<SiteVisit>.avgDurationFor(os:OS)=
    filter { it.os==os }
            .map (SiteVisit::duration)
            .average()

//Windows
println(log.avgDurationFor(OS.WINDOWS))

只要移动平台(Android 和 IOS数据)

  val avgMobilePlatform=log
        .filter { it.os in setOf(OS.IOS,OS.ANDROID) }
        .map (SiteVisit::duration)
        .average()

println(avgMobilePlatform)

显然需要更新公共函数了

fun List<SiteVisit>.avgDuration(predicate: (SiteVisit) -> Boolean)=
    filter(predicate)
            .map(SiteVisit::duration)
            .average()

测试:

    //Windows
println(log.avgDuration { it.os==OS.WINDOWS })

//mobile platform
println(log.avgDuration { it.os==OS.IOS || it.os ==OS.ANDROID })

println(log.avgDuration { it.os==OS.IOS && it.path =="/ryyy" })

内联函数inline:消除lambda的开销

inline fun<T> synchronized(lock: Lock, action:() ->T) :T{
lock.lock()
try {
    return action()
} finally {
    lock.unlock()
}
}

fun foo(l:Lock){
println("before sync")
synchronized(l){
    println("Action")
}
println("after action")
}


 /**
 *函数类型做参数,不是lambda,inline失效
 */
class LockOwner(val lock:Lock){
fun runUnderLock(body:() ->Unit){
    synchronized(lock,body)
}
}

class LockOwner2(val lock:Lock){
 fun _runUnderLock_(body: () -> Unit){
   lock.lock()
   try {
       body()
   } finally {
       lock.unlock()
   }
  }
}

kotlin中,filter,map函数被声明为内联函数。当出现大量数据处理时,可以通过 在链式后加asSequence(),用序列代替集合,但kotlin建议在处理大数据时用。

inline只能提高带有lambda参数的函数的性能.

java中try-with-resources在kotlin中的替代。

//java代码
 static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader bufferedReader=new BufferedReader(new FileReader(path))){
        return bufferedReader.readLine();
    }
}

//kotlin中使用use代替,use在kotlin中是内联函数
fun readFirstLineFromFile(path:String):String{
BufferedReader(FileReader(path)).use { 
    br -> return br.readLine()
}
}

lambda中的返回语句

data class Person2(val name: String ,val age:Int)

fun lookFofJim(people :List<Person2>){
for (person in people){
    if (person.name=="Jim") {
        println("找到了")
        return
    }
}
println("jim 没找到")
}

fun main(args: Array<String>) {
val people= listOf(Person2("fdaaf",34), Person2("trrt",73))
lookFofJim(people)
}

forEach依旧适用
people.forEach {
    if (it.name=="Jim") {
        println("找到了")
        return
    }
}

引入便签局部返回:@一定要有,边签名任意

fun lookFofJim2(people :List<Person2>){

people.forEach label@{
    if (it.name=="Jim") {
        println("找到了")
        return@label
    }
}
//总会执行
println("jim ...")
}

函数名也可以作为标签

fun lookFofJim(people :List<Person2>){
   /* for (person in people){
    if (person.name=="Jim") {
        println("找到了")
        return
    }
}
*/
people.forEach {
    if (it.name=="Jim") {
        println("找到了")
        return@forEach
    }
}
println("jim 没找到")
}

注意,当匿名函数中有return时,返回最近的匿名函数

fun lookFofJim3(people :List<Person2>){
people.forEach(fun(person) {
    if (person.name=="trrt") {
        println("找到了")
        return
    }
})
//总会执行
println("jim ...")
}

此时return是从fun(person)返回。

泛型:Kotlin泛型要求类型实参被显示地说明,或者能被编译器推导出来。

fun <T : Number> oneHalf(value :T) :Double{
return value.toDouble()/2.0
}

val nums= oneHalf(65.32)
println(nums)

fun <T: Comparable<T>> max (first:T,second:T):T{
    return if (first>second) first else second
// return if (first.compareTo(second)>0) first else second
}

println(max(23,546))

参数约定:
fun<T> ensureTrailingPeriod(seq:T) where T:CharSequence,T:Appendable{
if(!seq.endsWith('.')){
    seq.append('.')
}
}

val hello=StringBuilder("fafd fafddadf hello")
ensureTrailingPeriod(hello)
println(hello)

形参可空
class Processor<T> {
fun process(value :T){
    value?.hashCode()
}
}

val nullProcess=Processor<String?>()
nullProcess.process(null)

Any代替Any?形参非空
class Processor2<T : Any>{
fun process(value : T){
    value.hashCode()
}
}

声明带实例化参数的函数
inline fun <reified T> isA(value: Any) =value is T
println(isA<String>("ffdafadfadfadfadfd"))
结果:true

标准库函数:filterIsInstance
val items= listOf("faafd","fdf",122,"fddf1","113423")
println(items.filterIsInstance<String>())

关于reified。带reified类型参数的inline函数不能再java中调用。普通的inline可以被调用,但不能被内联。
filterIsInstances被标记为inline,但它并不期望lambda作为实参 。
目前,还不能把类,属性和非内联函数的类型参数标记为reified。当lambda因为性能被内联时,可以使用noinline标记。
.

  inline fun<reified T : Activity> Context.startActivity(){
    val intent= Intent(this,T::class.java)
    startActivity(intent)
}
Handler().postDelayed({
        startActivity<MainActivity>()
    },3000)

一个编译器通过不了的demo

fun addAnswer(list: MutableList<Any>){
list.add(43)
}

 val strings= mutableListOf("adf","dfadf")
 addAnswer(strings)

kotlin中List是只读集合
超类型概念:A是B的子类型,那么B就是A的超类型。
非空类型A是可空类型A?的子类型,但反过来不是。
不变型:对于任意类型A和B,MutableList<A>既不是MutableList<B>的子类型,也不是超类型,它就被称为该类型参数是不变型的。
协变:如果A是B的子类型,那么List<A>是List<B>的子类型,这样的类或者接口被称为协变。声明协变用out关键字。
逆变:反转子类型化关系。in关键字。

interface Produce<out T>{
fun produce():T
 }

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

推荐阅读更多精彩内容