Stream流中flatMap和map的理解 --- java

1.写在前面的话

  经常会遇到这种情况,想去整理一些东西,网上一看,已经有网友整理了,而且整理的还挺好,自己就懒得再去整理,而且工作中真正用到时,上网一搜,一般就能解决自己遇到的问题,于是就更不想去整理了…从大一到研究生毕业,接触计算机好多年了,但去年才真正开始写博客,期间有过多次这样的挣扎.今天又是从这种挣扎中走来,于是特意提醒一下自己,就算别人整理了,就算自己可能写的很差,但至少我没有让这段时间白白荒废掉,而且确实更加明白了自己要整理的东西…

2.直接上代码(可直接运行)

  下面的代码可以分成两个部分,上半部分是关于map的,由于map相对比较简单,所以栗子相对较少,flatMap一开始理解起来可能不是很容易理解,于是我用了三个栗子来帮助大家进行理解,大家需要着重理解为什么map不行以及flatMap的扁平化处理.看完之后多写写,相信大家肯定能明白flatMap的用法.

   下图是利用本文中的栗子对flatMap使用方法的分析
Stream流中flatMap和map的理解 --- java_第1张图片

具体代码

package com.nrsc.stream;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 玩具类
 */
class Toy {
    private String name;
    private String Color;

    public Toy(String name, String color) {
        this.name = name;
        Color = color;
    }

    public String getName() {
        return name;
    }

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

    public String getColor() {
        return Color;
    }

    public void setColor(String color) {
        Color = color;
    }

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

/**
 * 用户类
 */
class User {
    private String name;
    private int age;
    private List<Toy> toys;
    private Toy[] toyArray;

    public Toy[] getToyArray() {
        return toyArray;
    }

    public void setToyArray(Toy[] toyArray) {
        this.toyArray = toyArray;
    }

    public List<Toy> getToys() {
        return toys;
    }

    public void setToys(List<Toy> toys) {
        this.toys = toys;
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class StreamStatus {
    public static void main(String[] args) {
        String myAngry = "My code was changed by my colleague again. I was very angry.";
        /**
         *   Ⅰ  map 和 mapToInt/mapToLong/mapToDouble
         *         功能:map相对比较简单就是
         *              取出流中的数据分别对其进行做相应的操作-----和python里的map差不多
         */

        /** map输入类型为流中类型,输出类型任意*/
        Stream.of(myAngry.split(" ")).map(s -> s + "||").forEach(System.out::print);
        System.out.println("====================");

        /** mapToInt 输入类型为流中类型,输出类型只能为int ---- mapToLong/mapToDouble同理*/
        Stream.of(myAngry.split(" ")).mapToInt(s -> {
            System.out.print(" // ");
            return s.length();
        }).forEach(System.out::print);
        System.out.println("+++++++++++++++++++++");

        /**
         *  Ⅱ  flatMap
         *
         */

        System.out.println("=======================flatMap===========================");
        System.out.println("========================栗子1============================");

        /**
         * 栗子1
         * --------对于字符串数组而言,每个字符串又可以看成若干字母组成的集合,
         * --------该如何由字符串数组直接获取到这些字母的集合呢?
         */
        String[] language = {"java", "python", "matlab", "ruby", "php", "go"};

        /** 或许你会想到如下的表达式
         *  但是仔细分析一下,就可以知道,该表达式获取到的是每个单词字母数组的集合*/
        Arrays.stream(language).map(s -> s.split("")).collect(Collectors.toList());
        //验证如下
        Stream<String[]> stream = Arrays.stream(language).map(s -> s.split(""));

        List<String[]> list = Arrays.stream(language)
                .map(s -> s.split("")).collect(Collectors.toList());

        for (String[] strings : list) {
            for (String string : strings) {
                System.out.println(string);
            }
        }
        /**
         * 此时你就可以使用flatMap,
         * ★★需要注意的是★★
         * 假设flatMap中的lambda表达式为 A -> B
         *   那么A应该是一个集合, 或者说 可以看作集合的参数,B是由A产生的一个Stream流
         *   同时JDK会将所有流入flatMap的集合产生的Stream流合并成一个大的Stream流,然后才会离开flatMap
         *                                        ---------扁平化处理 (如果没理解,可以看文中的插图)
         */

        // ★ ★ ★list2_1与list2_2等价(当输入参数为1个时一般都可以使用方法引用来代替箭头表达式) ★ ★ ★
        /** 方式1*/
        List<String> list2_1 = Arrays.stream(language).map(s -> s.split(""))
                .flatMap(s -> Arrays.stream(s)).collect(Collectors.toList());

        List<String> list2_2 = Arrays.stream(language).map(s -> s.split(""))
                .flatMap(Arrays::stream).collect(Collectors.toList());

        /** 方式2*/
        List<String> list3 = Arrays.stream(language)
                .flatMap(s -> Arrays.stream(s.split(""))).collect(Collectors.toList());

        /** 方式3  注意下面这种方式要进行装箱操作,且该表达式获取到的是每个字母ASCII码值的集合*/
        List<Integer> list4 = Arrays.stream(language)
                .flatMap(s -> s.chars().boxed()).collect(Collectors.toList());


        /**
         *  栗子2
         *        ----对于一句英文来说,可以将其看作是若干单词组成的一个集合,
         *                      而每个单词又可以看成一个由若干字母组成的集合
         *
         *             那么求一句话中出现的所有不包括空格的字母,就可以按照如下的方式进行书写
         */

        System.out.println("========================栗子2============================");
        Stream.of(myAngry.split(" ")).flatMap(s -> s.chars().boxed()).distinct()
                .forEach(i -> System.out.print((char) i.intValue()));
        System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&");

        /** 或者如下的方式*/
        Stream.of(myAngry.split(" ")).map(s -> s.split(""))
                .flatMap(Arrays::stream).distinct().forEach(System.out::print);
        System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%");


        /**
         *   栗子3:
         *         假设有多个用户,每个用户又有若干个玩具,这些玩具有名字和颜色两个属性,
         *         那么如何通过Stream流直接由用户列表获取到所有用户的所有玩具的颜色呢?
         *
         */
        System.out.println("========================栗子3============================");
/**
 * 数组 -----
 *      ★★★★★注意★★★★★
 *       如果在flatMap中的lambda表达为A->B
 *         如果A是集合,B(由A产生的Stream流)需要按照集合的方式创建 --- > 集合实体.Stream  集合实体.parallelStream
 *         如果A是数组,BB(由A产生的Stream流)需要按照数组的方式创建----> Arrays.  Stream.等
 */
    User one = new User("阿大", 18);
    User two = new User("阿二", 16);
    User three = new User("阿三", 14);
    one.setToyArray(new Toy[]{new Toy("熊大", "棕色"), new Toy("黑猫警长", "黑白色")});
    two.setToyArray(new Toy[]{new Toy("手枪", "黑色"), new Toy("小汽车", "红色")});
    three.setToyArray(new Toy[]{new Toy("不倒翁", "黄色"), new Toy("铁环", "灰色")});


    User[] userArray = {one, two, three};
    Arrays.stream(userArray).map(User::getToyArray)
            .flatMap(Arrays::stream).map(Toy::getColor).forEach(System.out::println);
    System.out.println("");

    Stream.of(userArray).map(User::getToyArray)
            .flatMap(Arrays::stream).map(Toy::getColor).forEach(System.out::println);
    System.out.println("-------------------------------------------------------------------------------------");

        /**
         * 集合
         */
    List<User> userList = Arrays.asList(one, two, three);
    one.setToys(Arrays.asList(new Toy("熊大", "棕色"), new Toy("黑猫警长", "黑白色")));
    two.setToys(Arrays.asList(new Toy("手枪", "黑色"), new Toy("小汽车", "红色")));
    three.setToys(Arrays.asList(new Toy("不倒翁", "黄色"), new Toy("铁环", "灰色")));


    userList.stream().map(User::getToys)
            .flatMap(toy -> toy.stream()).map(Toy::getColor).forEach(System.out::println);
    System.out.println("=====================================================================================");

    userList.stream().map(User::getToys)
            .flatMap(Collection::stream).map(Toy::getColor).forEach(System.out::println);
    System.out.println("===================================并行流=============================================");
    userList.stream().map(User::getToys)
            .flatMap(toy -> toy.parallelStream()).map(Toy::getColor).forEach(System.out::println);
    }
}

你可能感兴趣的:(Lambda表达式)