【Kotlin 协程】Flow 操作符 ① ( 过渡操作符 | map 操作符 | transform 操作符 | 限长操作符 | take 操作符 )

news2024/11/24 13:02:00

文章目录

  • 一、过渡操作符
    • 1、map 操作符
    • 2、transform 操作符
  • 二、限长操作符 ( take 操作符 )





一、过渡操作符



过渡操作符 相关概念 :

  • 转换流 : 使用 过渡操作符 转换 Flow 流 ;
  • 作用位置 : 过渡操作符作用 于 流的上游 , 返回 流的下游 ;
  • 非挂起函数 : 过渡操作符 不是挂起函数 , 属于冷操作符 ;
  • 运行速度 : 过渡操作符 可以 快速返回 新的 转换流 ;

1、map 操作符


通过 map 操作符 , 可以操作每个元素 , 将元素转为另外一种类型的元素 ;

map 操作符原型 :

/**
 * 返回一个流,其中包含对原始流的每个值应用给定[transform]函数的结果。
 */
public inline fun <T, R> Flow<T>.map(crossinline transform: suspend (value: T) -> R): Flow<R> = transform { value ->
   return@transform emit(transform(value))
}

代码示例 : 将 Flow 中发射的 Int 元素 转为 字符串 ; 通过 map 操作符 , 将 Int 类型的元素 转为 字符串类型 元素 ;

package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            (0..3).asFlow()
                        // 通过 map 操作符将 Int 转为字符串元素
                        .map {
                            stringConvert(it)
                        }
                        .collect {
                            println("collect : ${it}")
                        }
        }
    }

    // 将 Int 转为 字符串
    suspend fun stringConvert(num: Int): String {
        delay(1000)
        return "convert $num"
    }
}

执行结果 :

2022-12-26 11:28:07.370 23972-23972/kim.hsl.coroutine I/System.out: collect : convert 0
2022-12-26 11:28:08.371 23972-23972/kim.hsl.coroutine I/System.out: collect : convert 1
2022-12-26 11:28:09.412 23972-23972/kim.hsl.coroutine I/System.out: collect : convert 2
2022-12-26 11:28:10.452 23972-23972/kim.hsl.coroutine I/System.out: collect : convert 3

在这里插入图片描述


2、transform 操作符


通过 transform 操作符 , 可以操作每个元素 , 可以在单个元素处理时 , 发射多次元素 ;

transform 操作符原型 :

/**
 * 将[transform]函数应用到给定流的每个值。
 *
 * ' transform '的接收者是[FlowCollector],因此' transform '是一个
 * 灵活的函数,可以转换发出的元素,跳过它或多次发出它。
 *
 * 该操作符泛化了[filter]和[map]操作符和
 * 可以用作其他操作符的构建块,例如:
 *
 * ```
 * fun Flow<Int>.skipOddAndDuplicateEven(): Flow<Int> = transform { value ->
 *     if (value % 2 == 0) { // Emit only even values, but twice
 *         emit(value)
 *         emit(value)
 *     } // Do nothing if odd
 * }
 * ```
 */
public inline fun <T, R> Flow<T>.transform(
    @BuilderInference crossinline transform: suspend FlowCollector<R>.(value: T) -> Unit
): Flow<R> = flow { // 注意:这里使用的是安全流,因为收集器对每个操作的转换都是公开的
    collect { value ->
        // 没有它,单元将被退回,TCE将不会生效,KT-28938
        return@collect transform(value)
    }
}

代码示例 :

package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            (0..3).asFlow()
                        .transform { it ->
                            // 在 transform 操作符中发射 2 个元素
                            emit(it)
                            emit(stringConvert(it))
                        }
                        .collect {
                            println("collect : ${it}")
                        }
        }
    }

    // 将 Int 转为 字符串
    suspend fun stringConvert(num: Int): String {
        delay(1000)
        return "convert $num"
    }
}

执行结果 :

2022-12-26 11:38:14.091 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : 0
2022-12-26 11:38:14.091 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : 0
2022-12-26 11:38:15.146 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : convert 0
2022-12-26 11:38:16.189 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : convert 0
2022-12-26 11:38:16.189 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : 1
2022-12-26 11:38:16.189 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : 1
2022-12-26 11:38:17.229 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : convert 1
2022-12-26 11:38:18.269 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : convert 1
2022-12-26 11:38:18.270 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : 2
2022-12-26 11:38:18.270 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : 2
2022-12-26 11:38:19.309 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : convert 2
2022-12-26 11:38:20.349 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : convert 2
2022-12-26 11:38:20.349 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : 3
2022-12-26 11:38:20.349 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : 3
2022-12-26 11:38:21.389 25902-25902/kim.hsl.coroutine I/System.out: 接收元素 : convert 3
2022-12-26 11:38:22.429 25902-25902/kim.hsl.coroutine I/System.out: 发射元素 : convert 3

在这里插入图片描述





二、限长操作符 ( take 操作符 )



通过 take 操作符 , 可以选择选取指定个数的发射元素 ;

如 : 在 Flow 流中发射了 4 个元素 , 但是调用了 Flow#take(2) , 只收集其中 2 个元素 ;

take 操作符原型 :

/**
 * 返回包含第一个[count]元素的流。
 * 当[count]元素被消耗时,原始流将被取消。
 * 如果[count]不是正数,抛出[IllegalArgumentException]。
 */
public fun <T> Flow<T>.take(count: Int): Flow<T> {
    require(count > 0) { "Requested element count $count should be positive" }
    return unsafeFlow {
        var consumed = 0
        try {
            collect { value ->
                // 注意:这个for take不是故意用collectWhile写的。
                // 它首先检查条件,然后对emit或emitAbort进行尾部调用。
                // 这样,正常的执行不需要状态机,只需要终止(emitAbort)。
                // 有关不同方法的比较,请参阅“TakeBenchmark”。
                if (++consumed < count) {
                    return@collect emit(value)
                } else {
                    return@collect emitAbort(value)
                }
            }
        } catch (e: AbortFlowException) {
            e.checkOwnership(owner = this)
        }
    }
}

代码示例 :

package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            (0..3).asFlow()
                        .take(2)
                        .collect {
                            println("接收元素 : ${it}")
                        }
        }
    }
}

执行结果 :

2022-12-26 11:42:25.560 27701-27701/kim.hsl.coroutine I/System.out: 接收元素 : 0
2022-12-26 11:42:25.560 27701-27701/kim.hsl.coroutine I/System.out: 接收元素 : 1

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115506.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大话JMeter2|正确get参数传递和HTTP如何正确使用

上节课展示了JMeter的基础用法&#xff1a;录制回放功能&#xff0c;断言&#xff0c;聚合报告。但是在无UI下如何进行接口的访问呢&#xff1f;如何正确get参数传递和HTTP如何正确使用。尤其是在无UI下进行接口的访问。小哥哥带着你用漫画来学习JMeter&#xff0c;让你在轻松的…

【MMAsia 2021】Patch-Based Deep Autoencoder for Point Cloud Geometry Compression

文章目录Patch-Based Deep Autoencoder for Point Cloud Geometry Compression压缩流程自编码架构实验结果Patch-Based Deep Autoencoder for Point Cloud Geometry Compression https://arxiv.org/abs/2110.09109 这篇论文使用深度自编码器&#xff0c;提出了一种基于分块&am…

发票识别OCR及查验API接口为企业化解难题

对于当今的现代企业来说&#xff0c;分散的财务管理模式效率不高&#xff0c;管理成本反而相对较高&#xff0c;制约了集团企业发展战略的实施&#xff0c;因而需要建设财务共享模式。一个企业要建成财务共享中心&#xff0c;面临的难题是大量的数据采集和信息处理工作&#xf…

一组类型相同的数据【C 数组】总结

作者 &#xff1a; 会敲代码的Steve 墓志铭&#xff1a;博学笃志 切问静思 前言&#xff1a;本文旨在复习C语言数组章节的知识点、分为以下几个部分&#xff1a; 什么是数组一维数组、一维数组的初始化、一维数组的遍历、冒泡排序。二维数组、二维数组的创建和初始化、二维数…

多功能采集仪VH03接口使用说明

传感器接口 传感器接口须使用设备专门配备的测线&#xff0c;一端为 DB9 一端为用颜色区分的多个鳄鱼夹&#xff0c;线&#xff08;鳄鱼夹&#xff09;颜色和功能定义详见“设备组成和接口定义” 。 充电和通讯接口 VH03 使用标准的 USB Type-C 接口完成设备充电和通讯&…

创建一个vue项目

文章目录前言一、安装node.js二、vue ui命令没有反应原因1.vue ui命令是vue 3.x版本以上才支持&#xff0c;因此需要更新vue的版本。2.更新vue版本2.1首先使用以下命令卸载旧版本2.2然后使用下面命令安装最新版本2.3查看是当前版本号2.4此时&#xff0c;输入 vue -h 命令查看co…

HMS Core 3D流体仿真技术,打造移动端PC级流体动效

移动设备硬件的高速发展&#xff0c;让游戏行业发生翻天覆地的变化&#xff0c;许多酷炫的游戏效果不再局限于电脑端&#xff0c;玩家在移动端就能享受到场景更逼真、画质更清晰、体验更流畅的游戏服务。但由于移动设备算力不足&#xff0c;为了实现真实感的水体效果&#xff0…

cesium地形上面绘点时,山背面点位始终显示在地形上

cesium地形上面绘点时&#xff0c;山背面点位始终显示在地形上&#xff0c;如下图&#xff1a; 深度检测也是打开的&#xff0c;各种方法试完之后&#xff0c;也没有找到问题&#xff0c;把viewer属性注释之后&#xff0c;就没有出现这个问题&#xff0c;于是一个个属性&#…

【LeetCode】C语言实现---用队列实现栈用栈实现队列

目录&#x1f449;用队列实现栈&#x1f449;用栈实现队列&#x1f449;用队列实现栈 入口&#xff1a;OJ 题目描述&#xff1a; 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 em…

redis的消息发布订阅实现

文章目录前言一、创建好springboot项目,引入核心依赖二、使用步骤1. 自定义一个消息接受类2.声名一个消息配置类3.编写一个测试类总结前言 一般项目中都会使用redis作为缓存使用,加速用户体验,实现分布式锁等等,redis可以说为项目中的优化,关键技术实现立下了汗马功劳.今天带来…

YonBuilder应用构建教程之移动端基础配置

在YonBuilder中除了PC端应用的构建外&#xff0c;我们还可以构建配套的移动端页面。对于同一个数据实体可以实现PC端和移动端的数据同步修改&#xff0c;使数据录入、修改、审批等更加便捷。本篇文章通过对员工信息实体的移动端页面构建来对YonBuilder移动端配置的基础流程进行…

利用ENVI对遥感图像校正

1.几何校正 引起图像几何变形一般分为两大类:系统性和非系统性。系统性一般由传感器本身引起&#xff0c;有规律可循和可预测性&#xff0c;可以用传感器模型来校正&#xff0c;卫星地面接收站已经完成这项工作;非系统性几何变形是不规律的&#xff0c;它可以是传感器平台本身…

【Axure高保真原型】移动端钱包原型模板

今天和大家分享移动端钱包的原型模板&#xff0c;里面包含了11大模块&#xff0c;各个模块都是高保真高交互的原型模板&#xff0c;大家可以在演示地址里体验哦 【原型预览及下载地址】 https://axhub.im/ax9/4c3757a85d201a4c/#c1 这个原型还可以在手机上演示哦&#xff0c…

Bitmiracle Docotic.Pdf Library 8.8.14015 Crack

C# 和 VB.NET 的 PDF 库 Docotic.Pdf 是用于 .NET 的高性能 C# PDF 库。您可以使用它在 .NET Core、ASP.NET、Windows Forms、WPF、Xamarin、Blazor、Unity 和 HoloLense 应用程序中创建、阅读和编辑 PDF 文档。 该库支持 .NET 6、.NET 5、.NET Standard/.NET Core 和 .NET 4.…

Opencv(C++)笔记--模板匹配cv::matchTemplate()和最值计算cv::minMaxLoc()

目录 1--模板匹配 1-1--OpenCV API 1-2--六种匹配方法 1-3--代码实例 2--最值计算 2-1--OpenCV API 1--模板匹配 使用模板图像与原图像进行匹配&#xff0c;OpenCV提供了相应的模板匹配函数cv::matchTemplate()&#xff0c;并支持六种模板匹配方法。 1-1--OpenCV API vo…

【Linux】Linux项目自动化构建工具——make/Makefile

我举报&#xff0c;有人不学习&#xff01;&#xff01;&#xff01; 文章目录一、makefile原理二、初步理解makefile的语法1.gcc如何得知&#xff0c;源文件不需要再编译了呢&#xff1f;2.为什么执行的指令是make和make clean呢&#xff1f;三、makefile的推导规则四、Linux…

2023年1月数据治理认证DAMA-CDGA/CDGP(线上)招生简章

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

C语言刷题系列——17.计算平均成绩 18.找出总分最高的学生19.通讯录排序

结构 - PTA练习题&#x1f424;计算平均成绩&#x1f3c0; 题目要求&#x1f3c0; 题解&#x1f4bb;step1.定义结构体&#x1f4bb;step2.输入N&#xff1b;随后N行 每行给出一位学生的信息&#x1f4bb;step3.求平均值&#x1f4bb;step4.输出平均线以下的学生的信息&#x1…

数据可视化最简单的方式-饼状图,折线图,条形图

一个软件或者网站分为前端&#xff0c;后端。 后端传统意义就是处理后端的数据。 后端又分为数据库编程人员和后端业务逻辑人员。 前端顾名思义解决后端传递的数据。传递的数据如何显示是前端人员考虑的问题。 前端人员不光要设计好网页界面&#xff0c;而且要将数据的可视…

嵌入式:ARM协处理器指令总结

文章目录&#xff08;一&#xff09;协处理器的数据操作二进制编码汇编格式&#xff08;二&#xff09;协处理器的数据存取二进制编码汇编格式&#xff08;三&#xff09;协处理器的寄存器传送二进制编码汇编格式未使用的指令空间ARM支持16个协处理器&#xff0c;用于各种协处理…