Java8——Stream流的使用(映射操作)

Stream API支持对每一个流元素应用相同的函数,同时将函数计算结果生成一个新的流,类似于映射操作。这种操作在实际开发中非常的有用,比如流元素是一批对象,现在我们需要获取全部对象的id集合,那么我们就可以使用Stream提供的map和flatMap这两个映射方法来完成。

  Stream API支持对每一个流元素应用相同的函数,同时将函数计算结果生成一个新的流,类似于映射操作。这种操作在实际开发中非常的有用,比如流元素是一批对象,现在我们需要获取全部对象的id集合,那么我们就可以使用Stream提供的map和flatMap这两个映射方法来完成。
  映射操作是一个中间操作!

1. map映射

< R > Stream< R > map(Function< ? super T,? extends R > mapper)

  返回由给定函数应用于此流的全部元素的结果组成的流。返回的流的元素数据类型就是函数返回的结果的数据类型。

使用案例:

/**
 * @author lx
 */
public class MapTest {
    List<Student> students = new ArrayList<>();

    @Before
    public void before() {
        students.add(new Student(1, 55, "小花"));
        students.add(new Student(2, 100, "小华"));
        students.add(new Student(3, 85, "晓华"));
        students.add(new Student(4, 70, "肖华"));
    }

    @Test
    public void test() {
        students.stream()
                //获取每一个学生对象的学生id集合
                .map(Student::getId)
                //这是一个终端消费操作,后面会讲
                .forEach(System.out::println);


        List<Integer> collect = students.stream()
                //获取每一个学生对象的学生id集合
                .map(Student::getId)
                //这是一个终端收集操作,后面会讲
                .collect(toList());
        System.out.println(collect);


        /*将小写字母转换为大写*/
        List<String> collected = Stream.of("a", "b", "C")
                .map(String::toUpperCase)
                .collect(toList());
        System.out.println(collected);
    }

    static class Student {
        private int id;
        private int score;
        private String name;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public int getScore() {
            return score;
        }

        public void setScore(int score) {
            this.score = score;
        }

        public String getName() {
            return name;
        }

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

        public Student(int id, int score, String name) {
            this.id = id;
            this.score = score;
            this.name = name;
        }

        public Student(int id) {
            this.id = id;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "age=" + id +
                    ", score=" + score +
                    ", name='" + name + '\'' +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Student)) return false;

            Student student = (Student) o;

            if (getId() != student.getId()) return false;
            if (getScore() != student.getScore()) return false;
            return getName() != null ? getName().equals(student.getName()) : student.getName() == null;
        }

        @Override
        public int hashCode() {
            int result = getId();
            result = 31 * result + getScore();
            result = 31 * result + (getName() != null ? getName().hashCode() : 0);
            return result;
        }
    }
}

2. flatMap扁平化

< R > Stream< R > flatMap(Function< ? super T,? extends Stream<? extends R >> mapper)

  返回由通过将提供的映射函数应用于每个元素而产生的映射流的内容来替换该流的每个元素的结果的流。每个映射的流在其内容被放入此流之后是closed 。(如果映射的流是null则使用空的流)。
  简单的说,flatMap函数的返回值必须是Stream< XXX >流类型,随后返回的结果流会被合并成一个流,那么最终的流元素类型就是XXX。而前面的map函数的返回值不一定是Stream< XXX >流类型,一般来说应该返回一个实体类型XXX,那么最终的流元素类型就是XXX;如果map返回Stream< XXX >流类型,那么最终的流元素类型就是Stream< XXX >。
  即map返回的结果将使用一个流来收集,最后返回这个流,而flatMap一定是返回一个流,随后将所有返回的流和并成一个流返回,里面的元素自然也到一块儿去了,这里也就是“扁平化”的由来!
  因此flatMap常被用在来将不同批次的数据拆分成单个元素随后合并的操作!

使用案例:

/**
 * @author lx
 */
public class FlatMapTest {

    List<String> words = new ArrayList<>();

    @Before
    public void before() {
        words.add("hello");
        words.add("word");
    }


    /**
     * 将words数组中的元素再按照字符拆分,然后字符去重,最终达到["h", "e", "l", "o", "w", "r", "d"]
     */
    @Test
    public void test2() {

        //如果用map,可以看到流就成了Stream<Stream<String>>类型,那么最后收集的元素就是Stream<String>类型
        List<Stream<String>> mapList = words.stream()
                .map(word -> Arrays.stream(word.split("")))
                .distinct()
                .collect(toList());
        System.out.println(mapList);


        //如果使用flatMap,那么就可以达到想要的结果
        List<String> flatMapList = words.stream()
                .flatMap(word -> Arrays.stream(word.split("")))
                .distinct()
                .collect(Collectors.toList());
        System.out.println(flatMapList);
    }

    /**
     * 原因
     */
    @Test
    public void test() {
        //可以看到Arrays.stream方法返回的就是Stream<String>类型
        Stream<String> stream = Arrays.stream("word".split(""));
        //如果使用map,那么返回的流就是一个Stream<Stream<String>>类型,流元素也是一个流……
        //因为map将Arrays.stream方法返回的Stream<String>作为流元素使用一个流进行收集,随后返回这个流
        Stream<Stream<String>> streamStream = words.stream().map(word -> Arrays.stream(word.split("")));
        //如果使用flatMap,那么返回的流就是一个Stream<String>类型,这才是正常的类型
        //因为flatMap将Arrays.stream方法返回的Stream<String>流进行了合并,随后返回合并之后的大流
        Stream<String> stringStream = words.stream().flatMap(word -> Arrays.stream(word.split("")));
    }
}

  • 发表于 2020-09-16 15:51
  • 阅读 ( 27 )

0 条评论

请先 登录 后评论
NX小编
NX小编

1209 篇文章

作家榜 »

  1. NX小编 1209 文章
  2. 58沈剑 309 文章
  3. 奈学教育 137 文章
  4. 李希沅 | 奈学教育 36 文章
  5. 江帅帅 | 奈学教育 29 文章
  6. 林淮川 | 奈学教育 12 文章
  7. 科技热点 10 文章
  8. 邱鹏超 2 文章