本文是 用Java DIY 函數(shù)式方法—— map 續(xù)篇, 解決如何使用java實(shí)現(xiàn)函數(shù)式方法-flatmap。
注意
- 不適合對函數(shù)式一點(diǎn)基礎(chǔ)都沒有的讀者
- DIY實(shí)現(xiàn)不是完美的,僅僅是用實(shí)例表達(dá)函數(shù)式方法的理解
- 這個(gè)系列文章不是分析java 8 stream中的方法源碼,而是對java 8 stream特性,結(jié)合Kotlin, Rxjava之類的理解烟零, 使用純java的方式實(shí)現(xiàn)類似的函數(shù)式方法瘪松。
- 需要對java 中的泛型以及Collection有了解
- 會(huì)用到j(luò)ava 8 lambda表達(dá)式
- 要實(shí)際代碼驗(yàn)證,需要 jdk 1.8
講解的模式如下:
- 給出某個(gè)場景
- 使用 java 8
- 使用DIY 函數(shù)實(shí)現(xiàn)
那就進(jìn)入主題吧: 用Java DIY 函數(shù)式方法——flatmap
DIY 函數(shù)式方法flatmap
作用: T -> Collection<R> 注意锨阿,這是DIY實(shí)現(xiàn)理解宵睦,Kotlin,java 8 stream各有自己的集合表達(dá)
/** 需求:
* 給定 1 個(gè) Integer集合[1,2,3,4,5]
* 將該集合轉(zhuǎn)換為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的變化墅诡, 上述需求有點(diǎn)特別壳嚎,需要將 [1, 2, 3, 4, 5] 其中的每一個(gè)都要添加 "a", "b", 然后把他們整合成一個(gè)集合。
要是只能使用map實(shí)現(xiàn),也可以雨饺, 可行思路是, 如有好的map思路,請留言1涸恪!样屠!
- [1,2,3,4,5] -> ["1a", "2a", "3a", "4a", "5a"]
- [1,2,3,4,5] -> ["1b", "2b", "3b", "4b", "5b"]
- 手動(dòng)合并穿撮,還需要排序達(dá)到 ["1a", "1b", "2a", "2b", "3a", "3b", "4a","4b", "5a", "5b"]
1. java 8 stream實(shí)現(xiàn)
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 + " ") );
說明: 上述一條鏈?zhǔn)秸{(diào)用,就解決了我們的需求
lamdba表達(dá)式痪欲,簡潔如下:
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實(shí)現(xiàn)业踢,Kotlin栗柒, java 8 stream各有自己的轉(zhuǎn)換關(guān)系!
所以知举,需要三個(gè)東西: 輸入 T瞬沦, 輸出 Collection<R>, 映射關(guān)系雇锡!
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>
是輸入?yún)?shù)的類型
Function<T, Collection<R>> function
是映射關(guān)系, T -> Collection<R>
//這里僅僅是演示
Collection<? super R> result = new ArrayList<>();
一直強(qiáng)調(diào) DIY的實(shí)現(xiàn)是有局限性的锰提,我這里是在java集合的基礎(chǔ)上曙痘,而且選用ArrayList作為實(shí)際的主體,要是其他數(shù)據(jù)結(jié)構(gòu)類型立肘,肯定就沒法使用边坤, 但是,不影響 講解flatmap實(shí)現(xiàn)的思路谅年!
如上惩嘉, 使用者,只需要關(guān)注 Function
接口的具體實(shí)現(xiàn)方法call的設(shè)計(jì)踢故。
使用方式如下:
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 + " "));
其他實(shí)例:將三個(gè)IntegerList整合為一個(gè)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);
小結(jié)
理解 T -> Collection<R>文黎,就明白了flatmap的原理了,遇到實(shí)際的情況殿较,可以考慮用flatmap實(shí)現(xiàn)耸峭,體會(huì)跟傳統(tǒng)的不同之處!
代碼上傳到 csdn 資源下載
喜歡淋纲,用實(shí)際點(diǎn)贊支持我吧劳闹! 歡迎留言討論!