对于RxJava中的concatMap和flatMap有什么区别感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍rxjava的map和flatmap的区别,并为您提供关于5张弹珠图彻底弄清RxJ
对于RxJava中的concatMap和flatMap有什么区别感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍rxjava的map和flatmap的区别,并为您提供关于5 张弹珠图彻底弄清 RxJS 的拉平策略:mergeMap、switchMap、concatMap、exhaustMap、Android进阶学习RxJava(四)map和flatMap等操作符使用从入门到精通、Java 8 Stream Api 中的 map和 flatMap 操作、Java 8 Stream Api 中的 map和 flatMap 操作方法的有用信息。
本文目录一览:- RxJava中的concatMap和flatMap有什么区别(rxjava的map和flatmap的区别)
- 5 张弹珠图彻底弄清 RxJS 的拉平策略:mergeMap、switchMap、concatMap、exhaustMap
- Android进阶学习RxJava(四)map和flatMap等操作符使用从入门到精通
- Java 8 Stream Api 中的 map和 flatMap 操作
- Java 8 Stream Api 中的 map和 flatMap 操作方法
RxJava中的concatMap和flatMap有什么区别(rxjava的map和flatmap的区别)
似乎这两个功能非常相似。它们具有相同的签名(接受rx.functions.Func1<? super T, ? extends Observable<?extends R>>func
),并且它们的大理石图看起来完全相同。无法在此处粘贴图片,但这是用于concatMap的图片,这是用于flatMap的图片。在结果的描述中似乎存在一些细微的差异Observable
,其中所产生的concatMap
包含通过合并产生的可观察变量产生的项目,而所产生的flatMap
包含通过首先合并所产生的可观察变量并发出合并结果而产生的项目。
但是,这种微妙之处对我来说还不清楚。任何人都可以更好地解释这种差异,理想情况下可以提供一些示例来说明这种差异。
答案1
小编典典如您所写,这两个函数非常相似,而细微的区别是创建输出的方式(应用映射功能之后)。
平面地图使用合并运算符,而concatMap使用concat运算符。
如您所见,concatMap输出序列是有序的-在
合并第二个Observable发射的任何项目之前,先发射第一个Observable发射的所有项目,同时合并flatMap输出序列-
合并的Observable发射的项目可能会出现在任何顺序,无论它们来自哪个可观察来源。
5 张弹珠图彻底弄清 RxJS 的拉平策略:mergeMap、switchMap、concatMap、exhaustMap
RxJS 的操作符理解起来确实比较复杂,比如最常用的几种 map 操作符,本篇就来使劲冲一冲它们!!
- 原创文章,非商业转载请说名出处
map 操作想必大家一定不陌生:
const { of } = Rx;
const { map } = RxOperators;
const namesObservable = of(''A'', ''B'');
namesObservable.pipe(
map(name => `map ${name}`)
)
namesObservable .subscribe(result => console.log(`${result}`))
// map A
// map B
很直观,因为 map 映射的是“值”,所以足够简单~
但是,如果说,map 映射的是 observable 呢 ?
const { of } = Rx;
const { map } = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return of(`${name} 1`,`${name} 2`);
}
namesObservable.pipe(
map(name => http(name))
)
namesObservable.subscribe(result => console.log(`${result}`))
// 则会得到两个 observable 对象
// ****observable{ .. }
// observable{ .. }
我们在 [](https://rxviz.com/)https://rxviz.com/ 的弹珠图中,可以清晰的看到:返回的仍是 observable
并且 observable 由最初的 1 个,变成了 2 个(圆圈就是 observable),数据仍在里面没有被订阅解析出来。
虽然,我们可以用粗暴的方法,在订阅 .subscribe
里面再次调用订阅 .subscribe
,则可得值:
const { of } = Rx;
const { map } = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return of(`${name} 1`,`${name} 2`);
}
namesObservable.pipe(
map(name => http(name))
)
namesObservable .subscribe(resultObservable => {
resultObservable.subscribe(result => console.log(`${result}`) )
})
// A1
// A2
// B1
// B2
但是,这样包裹写法注定是不优雅的,所以,为了解决这个差异,RxJS 引入了 —— Flattening(扁平化)策略!!
我们可以借助 flatMap 操作符,则能得到同样的解析值的效果~
flatMap 其实也就是我们熟知的 mergeMap 操作符;
代码如下:
const { of } = Rx;
const { mergeMap} = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return of(`${name} 1`,`${name} 2`);
}
namesObservable.pipe(
mergeMap(name => http(name))
)
namesObservable.subscribe(result => console.log(`${result}`))
// A1
// A2
// B1
// B2
更进一步,沿着这种偏平化策略的思路,除了 mergeMap,RxJS 又引入了 switchMap、concatMap 和 exhaustMap,它们能够提供不同方向的拉平策略。
我们再借助 [](https://rxviz.com/)https://rxviz.com/ 的弹珠图,一眼便能看到它们的差异:
设置一个定时器,每一秒都发出一个 observable,一共发 3 次,来看下分别得值;
- mergeMap
const { of,interval} = Rx;
const { mergeMap,take,map } = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}
namesObservable.pipe(
mergeMap(name => http(name))
)
mergeMap
会同时维护多个活动的内部订阅;
- switchMap
const { of,interval} = Rx;
const { switchMap,take,map } = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}
namesObservable.pipe(
switchMap(name => http(name))
)
switchMap
,在每次发出时,会取消前一个内部 observable 的订阅,然后订阅一个新的 observable;
- concatMap
const { of,interval} = Rx;
const { concatMap ,take,map } = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}
namesObservable.pipe(
concatMap (name => http(name))
)
concatMap
会在之前前一个内部 observable 完成后,才会订阅下一个;
- exhaustMap
const { of,interval} = Rx;
const { exhaustMap ,take,map } = RxOperators;
const namesObservable = of(''A'', ''B'');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}
namesObservable.pipe(
exhaustMap (name => http(name))
)
exhaustMap
映射成内部 observable,忽略其他值直到该 observable 完成;
OK,以上便是本篇分享。
觉得不错点个赞吧,您的鼓励,我的动力,坚持输出质量好文~~ 欢迎评论讨论
我是掘金安东尼,输出暴露输入,技术洞见生活。再会吧~~
Android进阶学习RxJava(四)map和flatMap等操作符使用从入门到精通
先介绍map概念
- 官方文档
transform the items emitted by an Observable by applying a function to each item.
- 通过对每个项应用一个函数来转换可观察对象发出的项。(百度翻译)
- 个人理解: Observable 到 Observer 之间传递的数据转换
- 重点: Transformation
简单的试试怎么用
- 假设古代钱币加工是先做成圆形
- 下一步是在圆形中打一个方孔
所以流程应该是这样
- 圆形金属-> map(打方孔) -> 钱币
开始撸码
- 先来最基础的发圆形钱币
Observable.just(new circleMoney(), new circleMoney())
.subscribe(new Action1<circleMoney>() {
@Override
public void call(circleMoney money) {
money.SayInfo();
}
});
- 然后使用map转换成发方钱币
//先定义个钱币接口
public interface SquareMoney {
void SayInfo(); //打印型号
void SetInfo(String info); //设置型号
}
//然后使用map改造成发方钱币
Observable.just(new circleMoney(), new circleMoney())
.map(new Func1<circleMoney, SquareMoney>() {
@Override
public SquareMoney call(circleMoney circleMoney) {
//类型转换,向上转换为方形钱币
SquareMoney circleMoney1 = (SquareMoney) circleMoney;
//设置封装信息为方形
circleMoney1.SetInfo("SquareMoney");
return circleMoney1;
}
})
.subscribe(new Action1<SquareMoney>() {
@Override
public void call(SquareMoney money) {
//打印最终封装信息
money.SayInfo();
}
});
总结
- map可以进行简单的类型转换,对于小型操作非常合适
- 重点是学习思维,map一系列的操作符用来对数据进行操作
类似的操作符还有
- flatMap 扁平化处理数据
- concatMap 顺序化处理数据
- filter:集合进行过滤
- each:遍历集合
- take:取出集合中的前几个
- skip:跳过前几个元素
先介绍flatMap概念
- flat是扁平的意思
官方解释
- flatMap使用一个指定的函数对原始Observable发射的每一项数据之行相应的变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。
- 这个方法是很有用的,例如,当你有一个这样的Observable:它发射一个数据序列,这些数据本身包含Observable成员或者可以变换为Observable,因此你可以创建一个新的Observable发射这些次级Observable发射的数据的完整集合。
个人理解
- flatMap将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable。
- 适用于大集合里还有小集合,造成多个复杂嵌套等灾难代码,
- 避免循环嵌套,优化代码结构使用
开始撸码
- 不知道各位有没有玩过套娃,一个大的里面有好几个小娃娃的那种玩具
- 假设有N个大点的套娃
- 每个套娃里有N个小套娃
- 输出每个大套娃里面的小套娃信息
//小套娃
class SmallMatryoshka {
private String name = "小套娃";//名字
}
//大套娃
class BigMatryoshka {
private String name = "大套娃";//名字
private List<SmallMatryoshka> smallMatryoshkaList;//包含小套娃的列表
}
//先创建一堆小套娃,放到List中
ArrayList<SmallMatryoshka> smallMatryoshkas = new ArrayList<>();
smallMatryoshkas.add(new SmallMatryoshka());
smallMatryoshkas.add(new SmallMatryoshka());
smallMatryoshkas.add(new SmallMatryoshka());
// 创建大套娃,并将小套娃列表放到大套娃中
BigMatryoshka bigMatryoshka = new BigMatryoshka();
bigMatryoshka.smallMatryoshkaList = smallMatryoshkas;
//大套娃列表,把大套娃放进去
List<BigMatryoshka> bigMatryoshkas = new ArrayList<BigMatryoshka>();
bigMatryoshkas.add(bigMatryoshka);
bigMatryoshkas.add(bigMatryoshka);
bigMatryoshkas.add(bigMatryoshka);
//输出大套娃列表里,大套娃包含的所有的小套娃
Observable.from(bigMatryoshkas)
.flatMap(new Func1<BigMatryoshka, Observable<SmallMatryoshka>>() {
@Override
public Observable<SmallMatryoshka> call(BigMatryoshka bigMatryoshka1) {
//转换成Observable后再次发送
return Observable.from(bigMatryoshka1.smallMatryoshkaList);
}
})
.subscribe(new Action1<SmallMatryoshka>() {
@Override
public void call(SmallMatryoshka smallMatryoshka) {
//打印套娃名称
LogUtils.e(smallMatryoshka.name);
}
});
总结
- 优化了非常多的循环代码,可读性,效率都高了很多
- 其他的操作符,挖个坑,以后慢慢填
Java 8 Stream Api 中的 map和 flatMap 操作
1.前言
Java 8 提供了非常好用的 Stream API ,可以很方便的操作集合。今天我们来探讨两个 Stream 中间操作 map(Function<? super T, ? extends R> mapper)
和 flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
2. map 操作
map
操作是将流中的元素进行再次加工形成一个新流。这在开发中很有用。比如我们有一个学生集合,我们需要从中提取学生的年龄以分析学生的年龄分布曲线。 放在 Java 8 之前 我们要通过新建一个集合然后通过遍历学生集合来消费元素中的年龄属性。现在我们通过很简单的流式操作就完成了这个需求。
示意图:
对应的伪代码:
// 伪代码
List<Integer> ages=studentList.stream().map(Student::getAge).collect(Collectors.toList());
3. flatMap 操作
通过上面的例子,map
操作应该非常好理解。那么 flatMap
是干嘛的呢? 这样我们把上面的例子给改一下,如果是以班级为单位,提取所有班级下的所有学生的年龄以分析学生的年龄分布曲线。这时我们使用上面的方法还行得通吗?
List<List<Student>> studentGroup= gradeList.stream().map(Grade::getStudents).collect(Collectors.toList());
通过上面的一顿操作,我们只能得到每个班的学生集合的集合 List<List<Student>>
。 我们还需要嵌套循环才能获取学生的年龄数据,十分不便。如果我们能返回全部学生的集合 List<Students>
就方便多了。 没错!flatMap
可以搞定!
// flatMap 提取 List<Students> map 提取年龄
List<Integer> ages = grades.stream().flatMap(grade -> grade.getStudents().stream()).map(Student::getAge).collect(Collectors.toList());
正如上面的伪代码所示,我们使用 flatMap
将所有的学生汇聚到一起。然后再使用 map
操作提取年龄。 flatMap
不同于 map
地方在于 map
只是提取属性放入流中,而 flatMap 先提取属性放入一个比较小的流,然后再将所有的流合并为一个流。有一种 “聚沙成塔” 的感觉。
再画一张图来加深理解:
4. 总结
map
操作和 flatMap
操作一旦你熟悉了,可以非常简便地解决一些数据流的操作问题。扩展一下知识,其实Java 8 中 不光 Stream 中存在这两种操作,其实 Optional<T>
中也存在这两种操作,作用都差不多。
关注公众号:Felordcn获取更多资讯
个人博客:https://felord.cn
Java 8 Stream Api 中的 map和 flatMap 操作方法
Java 8提供了非常好用的 Stream API ,可以很方便的操作集合。今天通过这篇文章给大家分享Java 8 Stream Api 中的 map和 flatMap 操作方法,需要的朋友可以参考下
1.前言
Java 8提供了非常好用的 Stream API ,可以很方便的操作集合。今天我们来探讨两个 Stream中间操作 map(Function super T, ? extends R> mapper) 和 flatMap(Function super T, ? extends Stream extends R>> mapper)
2. map 操作
map 操作是将流中的元素进行再次加工形成一个新流。这在开发中很有用。比如我们有一个学生集合,我们需要从中提取学生的年龄以分析学生的年龄分布曲线。
放在 Java 8 之前 我们要通过新建一个集合然后通过遍历学生集合来消费元素中的年龄属性。现在我们通过很简单的流式操作就完成了这个需求。
示意图:
对应的伪代码:
// 伪代码 List ages=studentList.stream().map(Student::getAge).collect(Collectors.toList());
3. flatMap 操作
通过上面的例子, map 操作应该非常好理解。那么 flatMap 是干嘛的呢? 这样我们把上面的例子给改一下,如果是以班级为单位,提取所有班级下的所有学生的年龄以分析学生的年龄分布曲线。这时我们使用上面的方法还行得通吗?
List> studentGroup= gradeList.stream().map(Grade::getStudents).collect(Collectors.toList());
通过上面的一顿操作,我们只能得到每个班的学生集合的集合 List> 。 我们还需要嵌套循环才能获取学生的年龄数据,十分不便。如果我们能返回全部学生的集合 List 就方便多了。 没错! flatMap 可以搞定!
// flatMap 提取 List map 提取年龄 List ages = grades.stream().flatMap(grade -> grade.getStudents().stream()).map(Student::getAge).collect(Collectors.toList());
正如上面的伪代码所示,我们使用 flatMap 将所有的学生汇聚到一起。然后再使用 map 操作提取年龄。 flatMap 不同于 map 地方在于 map 只是提取属性放入流中,而 flatMap 先提取属性放入一个比较小的流,然后再将所有的流合并为一个流。有一种 “聚沙成塔” 的感觉。
再画一张图来加深理解:
4. 总结
map 操作和 flatMap 操作一旦你熟悉了,可以非常简便地解决一些数据流的操作问题。扩展一下知识,其实Java 8 中 不光 Stream 中存在这两种操作,其实 Optional 中也存在这两种操作,作用都差不多。
以上所述是小编给大家介绍的Java 8 Stream Api 中的 map和 flatMap 操作方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小编网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
关于RxJava中的concatMap和flatMap有什么区别和rxjava的map和flatmap的区别的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于5 张弹珠图彻底弄清 RxJS 的拉平策略:mergeMap、switchMap、concatMap、exhaustMap、Android进阶学习RxJava(四)map和flatMap等操作符使用从入门到精通、Java 8 Stream Api 中的 map和 flatMap 操作、Java 8 Stream Api 中的 map和 flatMap 操作方法等相关知识的信息别忘了在本站进行查找喔。
本文标签: