用Java DIY 函數(shù)式方法—— flatmap

本文是 用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)贊支持我吧劳闹! 歡迎留言討論!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洽瞬,一起剝皮案震驚了整個(gè)濱河市本涕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伙窃,老刑警劉巖菩颖,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異为障,居然都是意外死亡晦闰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門鳍怨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呻右,“玉大人,你說我怎么就攤上這事鞋喇∩模” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵侦香,是天一觀的道長落塑。 經(jīng)常有香客問我,道長鄙皇,這世上最難降的妖魔是什么芜赌? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮伴逸,結(jié)果婚禮上缠沈,老公的妹妹穿的比我還像新娘。我一直安慰自己错蝴,他們只是感情好洲愤,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顷锰,像睡著了一般柬赐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上官紫,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天肛宋,我揣著相機(jī)與錄音州藕,去河邊找鬼。 笑死酝陈,一個(gè)胖子當(dāng)著我的面吹牛床玻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沉帮,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼锈死,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了穆壕?” 一聲冷哼從身側(cè)響起待牵,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喇勋,沒想到半個(gè)月后缨该,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茄蚯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年压彭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渗常。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壮不,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出皱碘,到底是詐尸還是另有隱情询一,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布癌椿,位于F島的核電站健蕊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏踢俄。R本人自食惡果不足惜缩功,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望都办。 院中可真熱鬧嫡锌,春花似錦、人聲如沸琳钉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歌懒。三九已至啦桌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間及皂,已是汗流浹背甫男。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工且改, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人查剖。 一個(gè)月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓钾虐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笋庄。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容