当前位置: 首页 > news >正文

Kotlin基础五

内容

  • Lambda表达式语法
  • Lambda表达式的优化
  • Lambda的作用域
  • Lambda在集合中常用的操作
  • MaxBy最大值函数,filter过滤集合,map转换一个新集合,forEach循环集合
  • 集合判断式 all ,any ,count ,find
  • list分组成map
  • 嵌套集合元素处理flatMap
  • 集合惰性操作

一Lambda表达式

1.1简介

java在jdk1.8的时候引入了Lambda表达式的支持,我记得Lambda表达式并不属于任何语言特有的,类似像正则表达式属于谁一样。他的本质是将一段代码当成值到处传递。依稀记得依赖第三方去使用Lambda表达式去写代码。java中的lambda和kotlin中的写法还有细微的区别。和java写法差别:

java中:

findViewById(R.id.tv).setOnClickListener(view-> {});
复制代码

Kotlin中:

tv.setOnClickListener { view-> }复制代码

1.2Lambda表达式的语法

它的本质是将一段代码当成值到处传递,可以被独立的声明并储存到变量中,但是一般用法还是声明它并传递给函数。

{ x: Int, y: Int -> x + y }复制代码

语法:最外层始终有花括号包裹,箭头左边参数没有用小括号括起来,箭头右边是方法体

如果你愿意,可以用一个变量引用着

var lam = { x: Int, y: Int -> x + y }复制代码

二Lambda和集合

2.1.MaxBy函数

MaxBy函数可用在任何集合中,作用:求集合中的最大值并返回,用法:

2.1.1集合中储存自定义对象:

val arr1 = listOf<Person>(Person(name = "张三", age = 15), Person(name = "李四", age = 30))
//按照表达式语法进行书写,并当成值传递
arr1.maxBy({ p: Person -> p.age }) 复制代码
代码说明:花括号中的代码片段是lambda表达式,把它 作为实参传给函数。这个lambda接收一个类型为Person的参数并返回它的年龄。

优化这段代码的语法让他更简介:

优化1:如果lambda表达式是函数调用的最后一个实参,它可以放到括号的外边。

arr1.maxBy(){ p: Person -> p.age }复制代码
优化2:当lambda是函数唯一的实参时,可以去掉调用代码中的空括号对:
arr1.maxBy{ p: Person -> p.age }复制代码

优化3:如果lambda参数的类型可以被推导出来,你就不需要显式地指定它。

arr1.maxBy { p -> p.age }复制代码

优化4:如果只有一个参数的lambda且这个参数的类型可以推断出来,就会生成参数it。

arr1.maxBy {it.age }复制代码

2.2forEach

作用:在集合中的每一个元素上都调用给定的lambda。

val errors = listOf<String>("403 sdfsdfsdf", "404 not dfudsfsd")复制代码

可以有一下写法:

errors.forEach({error:String->Log.e("rrrrr",error)})
errors.forEach(){error:String->Log.e("rrrrr",error)}
errors.forEach{error:String->Log.e("rrrrr",error)}
errors.forEach{error->Log.e("rrrrr",error)}
errors.forEach{Log.e("rrrrr",it)}复制代码

2.3Lambda的作用域

属性,方法内局部变量 都可以是使用和改变,但是java中方法内局部变量只能使用,但不能改变。

2.4filter

作用:遍历集合过滤掉让表达式返回false的元素,留下返回true的元素。原集合不变。

val index = arrayListOf<Int>(1, 2, 3, 4)
val newindex = index.filter { it % 2 == 0 }
Log.e("rrrrrr",newindex.toString())复制代码

上面的结果是一个新的集合,它只包含输入集合中那些满足判断式的元素。

2.5map

作用:从老集合中取出元素,加上逻辑生成一个新的集合。

val index = arrayListOf<Int>(1, 2, 3, 4)
Log.e("rrrrrrrrrr",index.map { it*it }.toString())复制代码

打印结果如下

[1, 4, 9, 16]

2.6 map集合的过滤和转换

键和值分别由各自的函数来处理。filterKeys和mapKeys过滤和变换map的键,而另外的
filterValues和mapValues过滤和变换对应的值。
val map = mapOf<String, String>("1" to "One", "2" to "Two")
val eee = map.filterKeys { it == "1" }.mapKeys { (it.key.toInt() * 10).toString() }
Log.e("rrrrrrr", eee.toString())复制代码

打印结果:{10=One} 这里返回的还是map集合

集合判断式“all”“any”“count”和“find”

另一种常见的任务是检查集合中的所有元素是否都符合某个条件(或者它的变种,是否存在符合的元素)。Kotlin中,它们是通过all和any函数表达。count函数检查有多少元素满足判断式,而find函数返回第一个符合条件的元素。

3.1 all

作用:判断集合中是否全部元素都满足你传入的条件,返回boolean值

val people = listOf(Person(" Alice", 18), Person("Bob", 31))
val all = people.all { it.age > 18 }复制代码

这里返回true。

3.2any

作用:判断集合中是否有满足条件的元素,返回boolean值

val people = listOf(Person(" Alice", 18), Person("Bob", 31))
val any = people.any { it.age > 32 }复制代码

这里返回false。

3.3count

作用:获取满足条件的元素的个数,返回Int

val people = listOf(Person(" Alice", 18), Person("Bob", 31))
val count = people.count { it.age > 20 }
复制代码

这里返回1

3.4find

作用:返回满足条件的第一个元素,返回集合中的元素类型

val people = listOf(Person(" Alice", 18), Person("Bob", 31))
val find = people.find { it.age > 20 }复制代码

这里返回 :Person(name=Bob, age=31)

四 list分组成map

作用:把符合条件的分成一组,不符合条件的分成一组,返回Map<Boolean,List<Person>>

val people = listOf(Person(" Alice", 18), Person("Bob", 30), Person("LiLei", 31))
val maps = people.groupBy { it.age > 18 }复制代码

打印结果:

{false=[Person(name= Alice, age=18)], true=[Person(name=Bob, age=30), Person(name=LiLei, age=31)]}复制代码

五嵌套集合的处理

5.1flatMap

作用,获取集合中嵌套的集合合并成一个集合

val books = listOf<Book>(Book("成功上位", arrayListOf("张三,李四")), Book("成功上位2", arrayListOf("王五", "赵六")))
val eee = books.flatMap { it.auther }复制代码

打印结果:[张三,李四, 王五, 赵六]

注意:这个和rxjava完全不同,不要混为一谈。如果这里用books.map { it.auther }返回的就是:[[张三,李四], [王五, 赵六]]

flatMap干了两件事:1干了map的事情。2把map中的多个集合合并成一个集合。

如果不想重复可以调用toset方法去重。

注意:链式集合函数调用这些函数会及早地创建中间集合,也就是说每一步的中间结果都被存储在一个临时列表。而非像rxjava那样流式调用。如果是大量数据进行操作,就会出现效率地下的问题,为此Kotlin工程师还给我们提供了流式调用。

六 序列:也叫惰性操作集合

解决的问题:中间不去创建集合,提高效率。

6.1需要先把集合转换成序列,操作之后,再把序列转换成集合

index.asSequence()
        .filter {
    Log.e("rrrrrr1",""+it)
    it%2==0 }.map {
    Log.e("rrrrrr2",""+it*it)
    it*it }
        .toList()复制代码

          这个时候就不会每次都去创建一个新的集合。就拿上边来说,执行filter被记录下来,延时计算,再执行map还是记录下来,延时计算,直到调用tolist的,才会去触发所有的延期计算。

6.2自己创建序列

前边的例子都是用集合转换成序列,这里我们说一下怎样自己创建序列。

例如:我们去计算100以内的自然数之和,代码可以这样写:

val sss = generateSequence(0, { it + 1 })
val www = sss.takeWhile { it <= 100 }
www.sum()复制代码

注意:这个例子中的sss和www都是有延期操作的序列。这些序列中的实际数字直到你调用末端操作(这里是sum)的时候才会求值。

七lambda传递给java方法

7.1函数式接口定义

当java中定义的接口里边只有一个抽象方法,我们就叫这样的接口为函数式接口。Kotlin允许你在调用接收函数式接口作为参数的方法时使用lambda。如android的点击事件的回调。

7.2如果一个方返回函数式接口,我们不能直接返回一个表达式:需要用构造方法包裹起来像这样:

错误:

fun  getRunnable():Runnable{

    return  {  }
}复制代码

需要这样包裹:

fun  getRunnable():Runnable{

    return Runnable {  }
}复制代码
八.带接收者的lambda:“with”

8.1定义

在lambda函数体内可以调用一个不同对象的方法,而无需显示的声明这个对象的引用的lambda叫作带接收者的lambda。

说的什么鬼话?别着急!往下看就懂了

继续往下看,假如我们有要打印A到Z的字符串的需求,我们大概会这样写:

fun getAToZ(): String {
    val stringbuffer = StringBuffer()
    for (c in 'a'..'z') {
        stringbuffer.append(c)
    }
    return stringbuffer.toString()
}复制代码

这里我们是不是在方法中使用了StringBuffer对象的方法,而且显示的声明了stringbuffer,而我们不要方法中出现这个stringbuffer引用的变量,并且修改为lambda的形式,这种就叫做带接收者的lambda。

知道了需求,我们怎么做呢?

Kotlin给我们提供了一个with的函数,来做这个事情,我们先用with去修改,然后再解释代码:

fun getAToZ(): String {
    val stringbuffer = StringBuffer()
    return with(stringbuffer) {
        for (c in 'a'..'z') {
            this.append(c)
        }
        this.toString()
    }

}复制代码
with结构看起来像是一种特殊的语法结构,但它实际上是一个 接收两个参数的函数:这个例子中两个参数分别是stringBuilder和一个lambda。只是后一个表达式写到了外边。

这里的this就是代表着stringbuffer,还记的扩展函数的this指的是扩展哪个类型的事例吗?这里指定的是传递过来的对象,也就是外部对象。

还是有stringbuffer,继续改进。。。

fun getAToZ(): String = with(StringBuffer()) {
    for (c in 'a'..'z') {
        this.append(c)
    }
    this.toString()
}复制代码

这是只是把代码块体变成表达式体,就完全消除了变量,让代码变得更加有可读性。注意这里的this可以省略。

假如想调用类中的方法,可以像这样修改,同时解决了方法名字一样导致的冲突

fun getAToZ(): String = with(StringBuffer()) {
    for (c in 'a'..'z') {
        this.append(c)
    }
    this@MainActivity.toString()
}


override fun toString(): String {
    return "============="
}复制代码
with返回的值是执行lambda代码的结果,该结果就是lambda中的最后一个表达式(的值)。

小结

  1.  lambda是把代码块当成值到处传递
  2. lambda省略到只用it的写法
  3. lambda作用范围
  4. 循环集合forEach,过滤集合filter,映射一个新集合map,求集合最大值maxBy
  5. 集合的判断,全部符合all,有符合的any,有多少符合的count,找到第一个符合条件的元素find
  6. 集合分组成map 用方法groupBy方法
  7. 嵌套集合数据合并flatMap
  8. 集合转化成序列提高效率,使用 asSequence方法,记得最后把序列再转化成集合
  9. java中的函数式接口是什么
  10. 使用with写一个带返回值的lambda表达式


相关文章:

  • 转:少走弯路,给Java 1~5 年程序员的建议
  • 吴恩达《Machine Learning Yearning》总结(21-30章)
  • ESP8266的低功耗方案-睡眠模式
  • NPOI 自定义单元格背景颜色-Excel
  • Android Studio Flavors的妙用(转)
  • linux下怎么卸载自带的JDK和安装想要的JDK
  • 1、win10下的Docker+Redis 的下载及简单使用
  • 单例设计模式
  • PHP多进程系列笔记(三)
  • Netty基础
  • 探讨.NET Core的未来
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • Mantis 1.3.13报表显示问题
  • SQL Server 与 DSN
  • 关于怎么在手机端实现一个拖拽的操作
  • 【译】JS基础算法脚本:字符串结尾
  • [译] React v16.8: 含有Hooks的版本
  • Android系统模拟器绘制实现概述
  • Apache Zeppelin在Apache Trafodion上的可视化
  • bootstrap创建登录注册页面
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • ES6 学习笔记(一)let,const和解构赋值
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • Javascript 原型链
  • JS+CSS实现数字滚动
  • Linux Process Manage
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • tensorflow学习笔记3——MNIST应用篇
  • 搭建gitbook 和 访问权限认证
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 选择阿里云数据库HBase版十大理由
  • 移动端高清、多屏适配方案
  • ​io --- 处理流的核心工具​
  • ​虚拟化系列介绍(十)
  • # C++之functional库用法整理
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (javascript)再说document.body.scrollTop的使用问题
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (三分钟)速览传统边缘检测算子
  • (一)基于IDEA的JAVA基础10
  • (转) Android中ViewStub组件使用
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET 8.0 发布到 IIS
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .net MVC中使用angularJs刷新页面数据列表
  • .Net 高效开发之不可错过的实用工具
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • @Documented注解的作用
  • @FeignClient注解,fallback和fallbackFactory
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录