前言

本文将介绍 Kotlin 中 序列(Sequence)的概念及使用,并介绍该惰性集合操作对集合链式调用性能优化背后的原理。

目录

序列(Sequence)

概念

在使用 Kotlin 集合操作符进行链式调用时,例如 map 和 filter 时,都会在函数内部创建中间集合,比如下面的例子,使用 map 和 filter 在 User 集合中筛选出性别为男的成员,返回结果是一个集合。

users.map(User :: sex).filter {it.sex.equals("male")}

序列的用法

序列的用法很简单,只需要再集合后添加asSeqence() 函数即可

users.asSequence().map(User :: sex).filter {it.sex.equals("male")}

这里插播一个概念,其中 User :: user 是成员引用,具体介绍如下

成员引用(Member References)

概念

成员引用可以使你方便的调用某个类的成员,这个成员包括对应类的属性或方法.双冒号前的是被引用的类,双冒号后是需要返回的属性或方法名,如下所示是返回 User 成员的 sex 属性:

User :: sex

成员引用可以方便的赋值给其他变量或函数,例如上述寻找性别为 male 的例子,也可以用稍微复杂的写法,如下:

users.map(user : User -> user.sex).filter {it.sex.equals("male")}

可见成员引用的写法可读性更强。

再谈序列

让我们回到序列介绍。上文提到使用 map 和 filter 时,都会在函数内部创建中间集合,这会导致一个问题,如果源列表,就是 users 中元素特别多,集合的链式处理会变得十分低效,原因是创建了多次中间集合。而如果先将待处理集合通过 asSequence() 方法转换为序列,再进行 map 和 filter 操作,就会变得十分高效。对于是否使用序列进行集合操作,有几个前提,如果使用不当,反而会造成性能损失。这里总结一下使用场景:

序列性能测试

上文提到,是否使用序列的条件之一是处理大量数据,那么这个阈值究竟是多少?下面来进行一个性能测试,构造一个商品列表,其中每个商品包含商品名和价格两个属性,现在要求出对每个商品的价格加价 100 后,价格为奇数 的商品的个数,这里用到了 count() 方法,作用是求得集合内满足 count 条件的元素的个数,代码如下:

/*** 商品类*/
data class Commodity(var name: String, var price: String)
import java.util.*fun main(args: Array<String>) {val commodityList = ArrayList<Commodity>()for (i in 0..1000000) {val goods = Commodity("商品 $i", i * 5)commodityList.add(goods)}val startTime = System.currentTimeMillis()commodityList.asSequence() // 使用此函数代表使用 Kotlin 序列功能.map { it.price + 100 }.count { it % 2 != 0 }println("consume time is ${System.currentTimeMillis() - startTime} ms")}

测试结果折线图如下,其中横坐标为集合内元素的个数,纵坐标为代码执行时间,橙色线代表未使用序列,蓝色线代表使用序列:

表格对比如下:

由图可得出如下结论:

  • 上文提到的阈值大致为「一百万」个元素,大于该阈值时,使用序列大致能带来 90 % 的性能提升
  • 在小于「十万」个元素时,使用序列反而会造成性能下降

    为什么序列会提高集合操作的性能?

    1. 序列对集合的操作是惰性的。
    2. 不需要额外的创建中间集合保存链式操作的中间结果

对于第一点,惰性这个词可能给人带来迷惑,这和使用序列后,集合的计算方式有关,下面来介绍这一点,在下面这个例子中,你需要在一个整型数据集合,将每个数乘以 2 ,并找出集合中小于 10 的第一个元素。

var result = listOf(2,4,6,8,10).asSequence.map(it * 2).find(it > 10)

find() 方法的作用是在集合中查找满足条件的第一个元素,并返回查找到的值。下图是 Kotlin 使用序列进行处理

由图可知,所谓惰性,就是在使用 map 或 filter 等操作符的时候,在代码的执行顺序上,不会优先遍历所有的集合,即偷个懒,先对集合中第一个元素进行 map 和 filter, 然后对该元素执行 find 操作,发现满足 find 的条件,就立刻返回结果,由此可见,在有 map 和 find 或 last 等操作符组合时,序列的性能优化能发生最大的作用。

小结

  1. 在进行集合操作时,使用序列操作符,可以降低集合操作的时间和占用的空间,降低时间的原因是惰性操作,降低空间占用的原因是序列在执行操作时不会创建中间集合。
  2. 序列操作虽好,但也要视业务场景决定是否使用,否则反而会降低效率。

想学习更多Android知识,或者获取相关资料请加入Android开发交流群:1018342383。 有面试资源系统整理分享,Java语言进阶和Kotlin语言与Android相关技术内核,APP开发框架知识, 360°Android App全方位性能优化。Android前沿技术,高级UI、Gradle、RxJava、小程序、Hybrid、 移动架构师专题项目实战环节、React Native、等技术教程!架构师课程、NDK模块开发、 Flutter等全方面的 Android高级实践技术讲解。还有在线答疑

转载于:https://blog.51cto.com/14332859/2402073

Kotlin 性能优化利器 —— Sqeuence 原理浅析相关推荐

  1. 【Elasticsearch】Elasticsearch的IndexSorting:一种查询性能优化利器

    1.概述 转载:Elasticsearch的IndexSorting:一种查询性能优化利器 前言 前两周写过一篇<基于Lucene查询原理分析Elasticsearch的性能>,在最后留了 ...

  2. 微信小程序交互性能优化利器WXS的使用(一)

    微信小程序交互性能优化利器WXS的使用 WXS简介 WXS原理 注意事项(划重点) WXS的使用 引入WXS WXS的响应事件(重要) 开始食用WXS 封装视图层WXML实用小方法 WXS简介 WXS ...

  3. html压缩原理,webpack--前端性能优化与Gzip原理

    目录 前言 前不久看过掘金小册<前端性能优化原理与实践>,受益匪浅."我深感性能优化实在是前端知识树中特别的一环--当你需要学习前端框架时,文档和源码几乎可以告诉你所有问题的答案 ...

  4. Android性能优化一绘制原理分析

    Android应用启动慢,使用时经常卡顿,是非常影响用户体验的,应该尽量避免出现. 1.卡顿的分类 按照场景分可以分为: UI绘制 绘制 刷新 应用启动 安装启动 冷启动 热启动 页面跳转 页面间切换 ...

  5. UITableVIew的性能优化-重用原理

    UITableVIew的性能优化:使用方法创建cell时,先优先从缓存池中找cell,找不到再创建新的cell,并且要绑定Identifer标示. 代码: -(UITableViewCell *)ta ...

  6. Linux性能优化--Tuned特性原理及使用指南

    tuned简介 对普通用户而言,Linux应用环境优化是比较困难的.领域多,范围广:CPU.存储.缓存策略.内存管理等涉及的参数.Linux内部虽然有默认设置值,可以应对大多数的情况场景,但是针对一些 ...

  7. spark性能优化 -- spark工作原理

    从本篇文章开始,将开启 spark 学习和总结之旅,专门针对如何提高 spark 性能进行总结,力图总结出一些干货. 无论你是从事算法工程师,还是数据分析又或是其他与数据相关工作,利用 spark 进 ...

  8. Blink/Flink作业 性能优化配置及原理

    高性能作业指南 本文通过代码和一些配置信息来优化blink/flink作业的性能. 共分为几部分: 1.group aggregate优化: 开启minibatch,开启localglobal,开启p ...

  9. PHP中被忽略的性能优化利器:生成器

    如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显.但是,生成 ...

最新文章

  1. iOS - 图文混排技术方案分享
  2. Python介绍以及Python 优缺点
  3. Linux 文件的权限
  4. js、css的阻塞问题
  5. 伪mac android,Mac,android sdk,monkey压力测试,真机
  6. 记录工作中常用的CSS3
  7. python连接postgresql数据库
  8. AWK学习笔记五:可执行AWK程序
  9. 八、jdk工具之JvisualVM之四--VisualVM 进行性能分析及调优
  10. 防范ARP网关欺骗, ip mac双向绑定脚本
  11. 《数字图像处理》实验五
  12. Win11任务栏怎么变小?Win11任务栏变小的设置方法
  13. 如何解决vue项目本地ip地址无法访问项目问题?【亲测有效】
  14. EMC trainning杂谈
  15. python小课堂28_python小课堂28
  16. 有哪些比较流行的 C、C++和Java 的入门级项目?
  17. 支付宝H5,微信H5,微信公众号支付回调
  18. 同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结
  19. 云创办公智慧企业丨企业的下一个前沿阵地
  20. PPPwizard1.4.3软件使用说明中文翻译稿

热门文章

  1. leetcode71
  2. python全栈学习--day40()
  3. 初始html(常用标签)
  4. js高级---js运行原理
  5. 转载-- http接口、api接口、RPC接口、RMI、webservice、Restful等概念
  6. C语言 printf格式化输出,参数详解
  7. Oracle 9i 数据库 创建数据库 Net 配置 创建表 SQL查询 创建存储过程 (图)
  8. 配置整合DWR3.0和Spring2.5使用annotation注解
  9. 操作Docker容器
  10. 1.简单认识PHP和环境搭建