Java8新特性之Stream的API常用函数使用及说明

2020-03-02  本文已影响0人  安仔夏天勤奋

因为学习了Lambda表达式,再学习Java8新特性之Stream的API常用函数使用及说明,两者结合起来,代码就可以玩得更溜,下面做Stream的一些常用函数使用及说明,方日后温习,如果发现有不足之处,请多多指教。

什么是Stream(流)?

Stream是数据渠道,用于操作数据源(如:集合,数组等)转成的元素序列,对集合中的每个元素进行一系列并行或者串行的流水线操作。

Stream的作用是什么(为什么需要Stream)?

Stream是Java8的一大亮点,它与java.io包中的InputStream、OutputStream是完全不同的概念;也不同于解析XML出来的Stream。
Stream是java对集合对象功能的增强,对集合对象进行各种非常方便、高效的聚合操作,或者对大指数据操作。Stream的API同样借助于Lambda表达式(支持函数式编程,代码非常简洁),提高编程效率和程序的可读性,同时它还提供了并行和串行这两种模式进行汇聚操。默认情况能充分利用cpu的资源(Stream操作是延迟执行的,需要结果的时候才执行)。

Stream操作的三步曲

  1. 创建Stream:通过一个数据源(如:数组,集合),获到一个流。
  2. 中间操作:一个中间操作链(如:filter,map等),对数据源的数据进行处理。
  3. 终止操作:一个终止操作,执行中间操作链,并产生结果。
Stream的步骤.png

Stream创建的四种方式

  1. Collection提供了两个方法,分别为stream()和parallelStream()。

    //通过List集合创建Stream
    List<String> list = new ArrayList<>();
    Stream<String> stream1 = list.stream();//获取一个顺序流
    Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
    
  2. 通过Arrays中的静态方法stream()获取一个数组流。

    //通过Arrays中的静态方法stream()获取一个数组流
    Student[] students = new Student[2];
    Stream<Student> stream = Arrays.stream(students);
    
  3. 通过Stream类中的静态方法of()。注意:这里可以是字符串,数组,集合等其他数据类型。

    //通过Stream类中的静态方法of()。注意:这里可以是字符串,数组,集合等其他数据类型。
    Stream<String> stream3 = Stream.of("java", "lambda", "stream", "6666");
    
  4. 创建无限流。

    //使用iterate()创建无限流,这个通常和limit()一起使用,限制流中元素的个数。
    //iterate()接受一个种子值,和一个UnaryOperator(例如 f)。然后种子值成为Stream的第一个元素,
    //f(seed) 为第二个,f(f(seed)) 第三个,以此类推.
    Stream<Integer> iterate = Stream.iterate(0, x -> x + 1);
    iterate.limit(5).forEach(System.out::println);
    
    //使用generate()创建无限流,通常跟limit()一起使用,限制流中元素的个数。
    //可以根据任何计算方式来生成,通过实现Supplier接口,你可以自己来控制流的生成。
    Stream<Long> generate = Stream.generate(new Supplier<Long>() {
        long a = 1, b = 2;
        @Override
        public Long get() {
            long temp = a + b;
            a = b;
            b = temp;
            return a;
        }
    });
    generate.limit(10).forEach(System.out::println);
    

Stream的中间操作

中间操作符(如:filter,map等),多个中间操作可以连接起来形成一条流水线形式对数据源的数据进行处理。注意:如果未触发终止操作(下面会进行介绍),中间操作是不会执行任何处理,在触发终止操作时会一次性全部执行中间操作链并产生结果。

中间操作有状态之分:无状态——指元素的处理不受之前元素的影响;有状态——指该操作只有拿到所有元素之后才能继续下去。

中间操作

Stream的终止操作(结束操作)

一个终止操作,执行中间操作链,并产生结果。终止操作有状态之分:非短路——指必须处理所有元素才能得到最终结果;短路——指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。

终止操作

Stream的实际操作

我们了解了Java8新特性Stream的API后,开始以代码实践操作一遍。

一、中间操作就是对容器(集合)的处理过程,包括:筛选(filter、limit、distinct、skip...),映射(map、flatMap...),排序(sorted...),消费(peek..)等 。先写一个学生科目分数对象,以便操作。

public class StudentSubject {
    private String studentName;
    private String subject;
    private Integer score;

    public StudentSubject(String studentName, String subject, Integer score) {
        this.studentName = studentName;
        this.subject = subject;
        this.score = score;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public Integer getScore() {
        return score;
    }
    public void setScore(Integer score) {
        this.score = score;
    }
    @Override
    public String toString() {
        return "StudentSubject{" +
                "studentName='" + studentName + '\'' +
                ", subject='" + subject + '\'' +
                ", score=" + score +
                '}';
    }
     @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        final StudentSubject ss = (StudentSubject) obj;
        if (this == ss) {
            return true;
        } else {
            return (this.studentName.equals(ss.studentName));
        }
    }
    @Override
    public int hashCode() {
        int hash_code = 7;
        hash_code = 13 * hash_code+ (studentName == null ? 0 : studentName.hashCode());
        return hash_code;
    }
}

注意:因为中间操作链在没有执行终止操作前是不会执行的,所有下面都是以执行forEach终止操作来验证中间操作链的使用。

筛选(filter、limit、distinct、skip...)

映射(map、flatMap...)

排序(sorted...)

消费(peek...)

二、终止操作,执行中间操作链,并产生结果。当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。之后如果想要操作就必须新打开流。终止操作包括:循环遍历操作(forEach、forEachOrdered)、收集操作(collect..)、 匹配与聚合操作(allMatch、max、min...)

循环遍历操作

收集操作

匹配、聚合操作

归约操作

转换操作

总结

注意

上一篇下一篇

猜你喜欢

热点阅读