java8中map和flatMap區(qū)別

1.函數(shù)定義比較

map注釋

    /**
     * Returns a stream consisting of the results of applying the given
     * function to the elements of this stream.
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @param <R> The element type of the new stream
     * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *               <a href="package-summary.html#Statelessness">stateless</a>
     *               function to apply to each element
     * @return the new stream
     */
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);

翻譯過來:

返回由將給定函數(shù)應(yīng)用于該流元素的結(jié)果組成的流。
這是一個(gè)中間操作。

參數(shù):
    映射器-適用于每個(gè)元素的無干擾、無狀態(tài)功能
類型參數(shù):
    新流的元素類型
返參:新流

也就是說你的集合中的元素是什么類型就返回該元素的流。

flatMap注釋:

    /**
     * Returns a stream consisting of the results of replacing each element of
     * this stream with the contents of a mapped stream produced by applying
     * the provided mapping function to each element.  Each mapped stream is
     * {@link java.util.stream.BaseStream#close() closed} after its contents
     * have been placed into this stream.  (If a mapped stream is {@code null}
     * an empty stream is used, instead.)
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @apiNote
     * The {@code flatMap()} operation has the effect of applying a one-to-many
     * transformation to the elements of the stream, and then flattening the
     * resulting elements into a new stream.
     *
     * <p><b>Examples.</b>
     *
     * <p>If {@code orders} is a stream of purchase orders, and each purchase
     * order contains a collection of line items, then the following produces a
     * stream containing all the line items in all the orders:
     * <pre>{@code
     *     orders.flatMap(order -> order.getLineItems().stream())...
     * }</pre>
     *
     * <p>If {@code path} is the path to a file, then the following produces a
     * stream of the {@code words} contained in that file:
     * <pre>{@code
     *     Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);
     *     Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));
     * }</pre>
     * The {@code mapper} function passed to {@code flatMap} splits a line,
     * using a simple regular expression, into an array of words, and then
     * creates a stream of words from that array.
     *
     * @param <R> The element type of the new stream
     * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *               <a href="package-summary.html#Statelessness">stateless</a>
     *               function to apply to each element which produces a stream
     *               of new values
     * @return the new stream
     */
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

翻譯過來:

返回由將該流的每個(gè)元素替換為通過將所提供的映射功能應(yīng)用到每個(gè)元素而產(chǎn)生的映射流的內(nèi)容的結(jié)果組成的流肛走。每個(gè)映射的流在其內(nèi)容已被放置到該流中之后被關(guān)閉假抄。(如果映射的流是空的拌牲,則使用空的流责循。)
    
這是一個(gè)中間操作贵试。

參數(shù):
    映射器-無干擾琉兜、無狀態(tài)功能,適用于產(chǎn)生新數(shù)值流的每個(gè)元素
類型參數(shù):
    新流的元素類型
返參:
    新流
Apinote:
    FlatMap()操作具有對(duì)該流的元素應(yīng)用一對(duì)多變換的效果毙玻,然后將所得到的元素展平到新的流中豌蟋。
案例.
  如果訂單是采購(gòu)訂單的流,并且每個(gè)采購(gòu)訂單包含一系列行項(xiàng)目桑滩,則以下將生成包含所有訂單中所有行項(xiàng)目的流:
   orders.flatMap(order -> order.getLineItems().stream())... 
  如果路徑是到文件的路徑梧疲,則以下會(huì)產(chǎn)生包含在該文件中的單詞的流:
    Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);
    Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));
  傳遞到FlatMap的映射器函數(shù)使用簡(jiǎn)單正則表達(dá)式將一行分割為單詞數(shù)組,然后從該數(shù)組創(chuàng)建一個(gè)單詞流 

我的理解是假如你的集合流中包含子集合,那么使用flatMap可以返回該子集合的集合流.

2.案例比較

假如我們有地址類运准,一個(gè)地址類包含多個(gè)城市將地址類作為集合幌氮,我們想輸出所有的城市的名字。

數(shù)據(jù)結(jié)構(gòu):

1.jpg

地址類

//地址類
public class Address {
    private String province;
    private List<String> cityList;//市集合
    public String getProvince() {
        return province;
    } 
    public void setProvince(String province) {
        this.province = province;
    }

    public List<String> getCityList() {
        return cityList;
    }

    public void setCityList(List<String> cityList) {
        this.cityList = cityList;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", cityList=" + cityList +
                '}';
    }
}

測(cè)試案例

    public static void main(String[] args) {

        List<String> cityListOne = new ArrayList<>();
        cityListOne.add("鄭州");
        cityListOne.add("濮陽(yáng)");
        List<String> cityListTwo = new ArrayList<>();
        cityListTwo.add("廊坊");
        cityListTwo.add("邢臺(tái)");
        List<String> cityListThree = new ArrayList<>();
        cityListThree.add("大同");
        cityListThree.add("太原");
        List<String> cityListFour = new ArrayList<>();
        cityListFour.add("南昌");
        cityListFour.add("九江");

        Address addressOne = new Address();
        addressOne.setProvince("河南");
        addressOne.setCityList(cityListOne);

        Address addressTwo = new Address();
        addressTwo.setProvince("河北");
        addressTwo.setCityList(cityListTwo);

        Address addressThree = new Address();
        addressThree.setProvince("山西");
        addressThree.setCityList(cityListThree);

        Address addressFour = new Address();
        addressFour.setProvince("江西");
        addressFour.setCityList(cityListFour);

        List<Address> addresseList = new ArrayList<>();
        addresseList.add(addressOne);
        addresseList.add(addressTwo);
        addresseList.add(addressThree);
        addresseList.add(addressFour);

        //使用map輸出所有的城市名稱
        addresseList.stream()
                .map(a -> a.getCityList())
                .forEach(cityList->{ cityList.forEach(city -> System.out.print(city));
        });
        System.out.println("");
        //使用flatMap輸出所有城市名稱
        addresseList.stream()
                .flatMap(a -> a.getCityList().stream())
                .forEach(city -> System.out.print(city));


    }

輸出結(jié)果

鄭州濮陽(yáng)廊坊邢臺(tái)大同太原南昌九江
鄭州濮陽(yáng)廊坊邢臺(tái)大同太原南昌九江

可以看出兩個(gè)循環(huán)結(jié)果一致胁澳,但是map處理方式是在foreach中將cityList作為集合再次循環(huán)该互,而flatMap可以直接將cityList中的城市直接進(jìn)行循環(huán)輸出。也就是說flatMap可以獲取集合中的集合的流在外層可以直接處理

3.map強(qiáng)行獲取流會(huì)如何韭畸?

如果我們使用map強(qiáng)行獲取流進(jìn)行循環(huán)會(huì)如何呢慢洋?



        //使用map輸出所有的城市名稱
        addresseList.stream()
                .map(a -> a.getCityList())
                .forEach(cityList->{ cityList.forEach(city -> System.out.print(city));
        });
  
        //使用map強(qiáng)行獲取流進(jìn)行輸出塘雳,寫法和flatMap一致
        addresseList.stream()
                .map(a -> a.getCityList().stream())
                .forEach(city->System.out.println(city));
 
        //使用flatMap輸出所有城市名稱
        addresseList.stream()
                .flatMap(a -> a.getCityList().stream())
                .forEach(city -> System.out.print(city));

打印結(jié)果:

鄭州濮陽(yáng)廊坊邢臺(tái)大同太原南昌九江
java.util.stream.ReferencePipeline$Head@21588809
java.util.stream.ReferencePipeline$Head@2aae9190
java.util.stream.ReferencePipeline$Head@2f333739
java.util.stream.ReferencePipeline$Head@77468bd9
鄭州濮陽(yáng)廊坊邢臺(tái)大同太原南昌九江

可以看到使用map如果和flatMap寫法一樣強(qiáng)行獲取流進(jìn)行打印,打印的是流對(duì)象的信息普筹,而不是流對(duì)象中的集合信息败明。

4.使用多次flatMap

flatMap也可以使用多次,則會(huì)把更深一層的集合流中的數(shù)據(jù)在外層進(jìn)行處理

在上面的案例中太防,我們假如再添加一個(gè)用戶類 用戶類中包含地址類集合

數(shù)據(jù)結(jié)構(gòu)

2.jpg

用戶類

public class User {
    private String name;
    private List<Address> addressList;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Address> getAddressList() {
        return addressList;
    }

    public void setAddressList(List<Address> addressList) {
        this.addressList = addressList;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", addressList=" + addressList +
                '}';
    }
}

測(cè)試案例

    public static void main(String[] args) {

        List<String> cityListOne = new ArrayList<>();
        cityListOne.add("鄭州");
        cityListOne.add("濮陽(yáng)");
        List<String> cityListTwo = new ArrayList<>();
        cityListTwo.add("廊坊");
        cityListTwo.add("邢臺(tái)");
        List<String> cityListThree = new ArrayList<>();
        cityListThree.add("大同");
        cityListThree.add("太原");
        List<String> cityListFour = new ArrayList<>();
        cityListFour.add("南昌");
        cityListFour.add("九江");

        Address addressOne = new Address();
        addressOne.setProvince("河南");
        addressOne.setCityList(cityListOne);

        Address addressTwo = new Address();
        addressTwo.setProvince("河北");
        addressTwo.setCityList(cityListTwo);

        Address addressThree = new Address();
        addressThree.setProvince("山西");
        addressThree.setCityList(cityListThree);

        Address addressFour = new Address();
        addressFour.setProvince("江西");
        addressFour.setCityList(cityListFour);

        List<Address> addresseListOne = new ArrayList<>();
        addresseListOne.add(addressOne);
        addresseListOne.add(addressTwo);
        List<Address> addresseListTwo = new ArrayList<>();
        addresseListTwo.add(addressThree);
        addresseListTwo.add(addressFour);

        //新增用戶來包含地址集合
        List<User> userList = new ArrayList<>();
        User u1 = new User();
        u1.setName("張三");
        u1.setAddressList(addresseListOne);

        User u2 = new User();
        u2.setName("李四");
        u2.setAddressList(addresseListTwo);

        userList.add(u1);
        userList.add(u2);



        //使用map輸出所有的城市名稱
        userList.stream()
                .map(u->u.getAddressList())
                .forEach(addressList->{
                    addressList.forEach(address -> {
                        address.getCityList().forEach(city->{
                            System.out.print(city);
                        });
                    });
                });

        System.out.println("");//換行
        //使用flatMap輸出所有城市名稱
        userList.stream()
                .flatMap(u -> u.getAddressList().stream())
                .flatMap(a -> a.getCityList().stream())
                .forEach(city -> System.out.print(city));


    }

打印結(jié)果

鄭州濮陽(yáng)廊坊邢臺(tái)大同太原南昌九江
鄭州濮陽(yáng)廊坊邢臺(tái)大同太原南昌九江

可以看出flatMap可以使用多次將更深一層的集合流中的數(shù)據(jù)拿到外層進(jìn)行處理妻顶。而使用map則相當(dāng)繁瑣


以上就是我對(duì)java8中mapflatMap的理解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蜒车,隨后出現(xiàn)的幾起案子讳嘱,更是在濱河造成了極大的恐慌,老刑警劉巖酿愧,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沥潭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嬉挡,警方通過查閱死者的電腦和手機(jī)钝鸽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來庞钢,“玉大人拔恰,你說我怎么就攤上這事』ǎ” “怎么了颜懊?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)风皿。 經(jīng)常有香客問我河爹,道長(zhǎng),這世上最難降的妖魔是什么桐款? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任昌抠,我火速辦了婚禮,結(jié)果婚禮上鲁僚,老公的妹妹穿的比我還像新娘。我一直安慰自己裁厅,他們只是感情好冰沙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著执虹,像睡著了一般拓挥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袋励,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天侥啤,我揣著相機(jī)與錄音当叭,去河邊找鬼。 笑死盖灸,一個(gè)胖子當(dāng)著我的面吹牛蚁鳖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赁炎,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼醉箕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了徙垫?” 一聲冷哼從身側(cè)響起讥裤,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎姻报,沒想到半個(gè)月后己英,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吴旋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年损肛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邮府。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荧关,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出褂傀,到底是詐尸還是另有隱情忍啤,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布仙辟,位于F島的核電站同波,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏叠国。R本人自食惡果不足惜未檩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粟焊。 院中可真熱鬧冤狡,春花似錦、人聲如沸项棠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)香追。三九已至合瓢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間透典,已是汗流浹背晴楔。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工顿苇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人税弃。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓纪岁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親钙皮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜂科,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354