本文是 用Java DIY 函数式方法—— map 续篇, 解决如何使用java实现函数式方法-flatmap。
注意
- 不适合对函数式一点基础都没有的读者
- DIY实现不是完美的,仅仅是用实例表达函数式方法的理解
- 这个系列文章不是分析java 8 stream中的方法源码,而是对java 8 stream特性,结合Kotlin, Rxjava之类的理解, 使用纯java的方式实现类似的函数式方法。
- 需要对java 中的泛型以及Collection有了解
- 会用到java 8 lambda表达式
- 要实际代码验证,需要 jdk 1.8
讲解的模式如下:
- 给出某个场景
- 使用 java 8
- 使用DIY 函数实现
那就进入主题吧: 用Java DIY 函数式方法——flatmap
DIY 函数式方法flatmap
作用: T -> Collection<R> 注意,这是DIY实现理解,Kotlin,java 8 stream各有自己的集合表达
/** 需求:
* 给定 1 个 Integer集合[1,2,3,4,5]
* 将该集合转换为String类型集合["1a", "1b", "2a", "2b", "3a", "3b", "4a","4b", "5a", "5b"]
* 思路: [1,2,3,4,5] -> ["1a", "1b"], ["2a", "2b"], ["3a", "3b"], ["4a","4b"], ["5a", "5b"]
* -> ["1a", "1b", "2a", "2b", "3a", "3b", "4a","4b", "5a", "5b"]
*/
分析: map能解决的是 T -> R的变化, 上述需求有点特别,需要将 [1, 2, 3, 4, 5] 其中的每一个都要添加 "a", "b", 然后把他们整合成一个集合。
要是只能使用map实现,也可以, 可行思路是, 如有好的map思路,请留言!!!
- [1,2,3,4,5] -> ["1a", "2a", "3a", "4a", "5a"]
- [1,2,3,4,5] -> ["1b", "2b", "3b", "4b", "5b"]
- 手动合并,还需要排序达到 ["1a", "1b", "2a", "2b", "3a", "3b", "4a","4b", "5a", "5b"]
1. java 8 stream实现
List<Integer> integerList = Arrays.asList(1,2,3,4,5);
integerList.stream()
.flatMap(new Function<Integer, Stream<String>>() {
@Override
public Stream<String> apply(Integer integer) {
return Arrays.asList(integer + "a", integer + "b").stream();
}
}).forEach( item -> out.print(item + " ") );
说明: 上述一条链式调用,就解决了我们的需求
lamdba表达式,简洁如下:
integerList.stream()
.flatMap(integer -> Arrays.asList(integer + "a", integer + "b").stream())
.forEach(item -> out.print(item + " ") );
2. DIY flatmap
在DIY 之前,需要梳理 flatmap的 核心是什么?
T -> Collection<R>
注意:这是DIY flatmap基于Collection实现,Kotlin, java 8 stream各有自己的转换关系!
所以,需要三个东西: 输入 T, 输出 Collection<R>, 映射关系!
public static <T, R> Collection<? super R> flatMap(Collection<? extends T> collection,
Function<T, Collection<R>> function) {
Collection<? super R> result = new ArrayList<>();//这里仅仅是演示
for(T item: collection){
result.addAll(function.call(item));
}
return result;
}
public interface Function<T, R>{
R call(T item);//T -> R
}
其中: Collection<? super R>
是flatmap返回值类型, Collection<? extends T>
是输入参数的类型
Function<T, Collection<R>> function
是映射关系, T -> Collection<R>
//这里仅仅是演示
Collection<? super R> result = new ArrayList<>();
一直强调 DIY的实现是有局限性的,我这里是在java集合的基础上,而且选用ArrayList作为实际的主体,要是其他数据结构类型,肯定就没法使用, 但是,不影响 讲解flatmap实现的思路!
如上, 使用者,只需要关注 Function
接口的具体实现方法call的设计。
使用方式如下:
List<Integer> integerList = Arrays.asList(1,2,3,4,5);
flatMap(integerList, new Function<Integer, Collection<String>>() {
@Override
public Collection<String> call(Integer item) {
return Arrays.asList(item + "a", item + "b");
}
}).forEach(item -> out.print(item + " ") );
lambda简化:
flatMap(integerList, integer -> Arrays.asList(integer + "a", integer + "b") )
.forEach(item -> out.print(item + " "));
其他实例:将三个IntegerList整合为一个List [1], [2,3], [4,5,6] -> [1,2,3,4,5,6]
Collection<List<Integer>> input = Arrays.asList(
Arrays.asList(1),
Arrays.asList(2,3),
Arrays.asList(4, 5, 6));
flatMap(input, item -> new ArrayList<Integer>(item))
.forEach(out::println);
小结
理解 T -> Collection<R>,就明白了flatmap的原理了,遇到实际的情况,可以考虑用flatmap实现,体会跟传统的不同之处!
代码上传到 csdn 资源下载
喜欢,用实际点赞支持我吧! 欢迎留言讨论!
网友评论