Java8特性: stream

Posted 唐微港

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8特性: stream相关的知识,希望对你有一定的参考价值。

串行流

什么是Stream流

java.util.stream中定义的流,其中提供了一些常用的API让我们对数据进行处理。

流API中的流操作的数据源,是数组或者是集合。它本身是不存储数据的,只是移动数据,在移动过程中可能会对数据进行过滤,排序或者其它操作

但是,一般情况下(绝大数情况下),流操作本身不会修改数据源,比如,对流排序不会修改数据源的顺序。相反,它会创建一个新的流,其中包含排序后的结果。

演示实例准备

  1. 首先创建一个Student类,以后演示每次都使用这个类

    public class Student {
        private Integer id;
        private String name;
        private Integer age;
        private Double score;
        public Student() {
        }
        public Student(Integer id, String name, Integer age, Double score) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.score = score;
        }
        //getter和setter方法
        //toString方法
    }
    
    
  2. 然后下面再创建一个StudentData类,用于获取其数据

    public class StudentData {
        public  static List<Student> getStudents(){
            List<Student> list = new ArrayList<>();
            list.add(new Student(1,"刘备",18,90.4));
            list.add(new Student(2,"张飞",19,87.4));
            list.add(new Student(3,"关羽",21,67.4));
            list.add(new Student(4,"赵云",15,89.4));
            list.add(new Student(5,"马超",16,91.4));
            list.add(new Student(6,"曹操",19,83.4));
            list.add(new Student(7,"荀彧",24,78.4));
            list.add(new Student(8,"孙权",26,79.4));
            list.add(new Student(9,"鲁肃",21,93.4));
            return list;
        }
    }
    

创建Stream流的几种方式

  1. 通过一个集合创建Stream

    @Test
    public void test1(){
        List<Student> studentList = StudentData.getStudents();
        //第一种:返回一个顺序流
        Stream<Student> stream = studentList.stream();
        //第二种:返回一个并行流
        Stream<Student> stream2 = studentList.parallelStream();
    }
    
    
  2. 通过一个数组创建Stream

        @Test
        public void test2(){
            //获取一个整形Stream
            int[] arr = new int[]{1,2,34,4,65,7,87,};
            IntStream intStream = Arrays.stream(arr);
            //获取一个Student对象Stream
            Student[] students = StudentData.getArrStudents();
            Stream<Student> stream = Arrays.stream(students);
    
        }
    
    
  3. 通过Stream.of

        @Test
        public void test3(){
            Stream<Integer> integerStream = Stream.of(1, 2, 3, 5, 6, 7, 8);
            Stream<String> stringStream = Stream.of("1", "2", "3", "4", "5");
            Stream<Student> studentStream = Stream.of(
                    new Student(1, "刘备", 24, 90.4),
                    new Student(2, "张飞", 19, 87.4),
                    new Student(3, "关羽", 21, 67.4));
        }
    
  4. 创建一个无限流。使用generate方法生成的Stream通常用于随机数和常量

        @Test
        public void test4(){
            //每隔5个数取一个,从0开始,此时就会无限循环
            Stream.iterate(0,t->t+5).forEach(System.out::println);
            //每隔5个数取一个,从0开始,只取前5个数
            Stream.iterate(0,t->t+5).limit(5).forEach(System.out::println);
            //取出一个随机数
            Stream.generate(Math::random).limit(5).forEach(System.out::println);
        }
    

stream操作方法分类

中间聚合操作:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 skip、 parallel、 sequential、 unordered。(过度可以继续连调)

最终输出操作:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、iterator。(最终方法不能继续连调)

短路操作:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit。

常见Stream的API

  1. 筛选和切片

        @Test
        public void test1(){
            List<Student> list  = StudentData.getStudents();
            //(1)过滤:过滤出所有年龄大于20岁的同学
            list.stream().filter(item->item.getAge()>20).forEach(System.out::println);
            //(2)截断流:筛选出前3条数据
            list.stream().limit(3).forEach(System.out::println);
            //(3)跳过元素:跳过前5个元素
            list.stream().skip(5).forEach(System.out::println);
            //(4)过滤重复数据:
            list.stream().distinct().forEach(System.out::println);
        }
    
    
  2. 映射

    将Stream中的元素进行映射转换,比如将“a”转为“A”,期间生产了新的Stream。同时为了提升效率,官方也提供了封装好的方法:mapToDouble,mapToInt,mapToLong。

        @Test
        public  void test2(){
            //(1)map操作
            List<String> list  = Arrays.asList("java","python","go");
            Stream<String> stream = list.stream();
            //此时每一个小写字母都有一个大写的映射
            stream.map(str -> str.toUpperCase()).forEach(System.out::println);
            //筛选出所有的年龄,再过滤出所有大于20的年龄有哪些
            List<Student> studentList  = StudentData.getStudents();
            Stream<Student> stream1 = studentList.stream();
            Stream<Integer> ageStream = stream1.map(Student::getAge);
            ageStream.filter(age->age>20).forEach(System.out::println);
            //(2)floatMap:将流中的每一个值换成另外一个流
        }
    
    
  3. 排序

        public  void test3(){
            //(1)自然排序
            List<Integer> list  = Arrays.asList(4,3,7,9,12,8,10,23,2);
            Stream<Integer> stream = list.stream();
            stream.sorted().forEach(System.out::println);
            //(2)对象排序:对象类可以先实现comparable接口,或者是直接指定
            //第一种:先实现compable接口
            List<Student> studentList  = StudentData.getStudents();
            studentList.stream().sorted().forEach(System.out::println);
            //第二种:直接指定comparable
            List<Student> studentList1  = StudentData.getStudents();
            studentList1.stream()
                    .sorted((e1,e2)-> Integer.compare(e1.getAge(),e2.getAge()))
                    .forEach(System.out::println);
        }
    
  4. 匹配和查找(最终)

        public void test1(){
            List<Student> list  = StudentData.getStudents();
            //(1)判断所有的学生年龄是否都大于20岁
            boolean allMatch = list.stream().allMatch(item -> item.getAge() > 20);
            //(2)判断是否存在学生的年龄大于20岁
            boolean anyMatch = list.stream().anyMatch(item -> item.getAge() > 20);
            //(3)判断是否存在学生叫曹操
            boolean noneMatch = list.stream().noneMatch(item -> item.getName().equals("曹操"));
            //(4)查找第一个学生
            Optional<Student> first = list.stream().findFirst();
            //(5)查找所有的学生数量
            long count = list.stream().count();
            long count1 = list.stream().filter(item -> item.getScore() > 90.0).count();
            //(6)查找当前流中的元素
            Optional<Student> any = list.stream().findAny();
            //(7)查找学生最高的分数:Student实现了comparable接口的话,可直接比较
            Stream<Double> doubleStream = list.stream().map(item -> item.getScore());
            doubleStream.max(Double::compare);
            //(8)查找学生最低的分数
        }
    
    
  5. 归约(最终)

        public void test2(){
            //(1)计算数的总和
            List<Integer> list = Arrays.asList(1,2,3,4,5);
            list.stream().reduce(0,Integer::sum);
            //(3)计算学生总分
            List<Student> studentList = StudentData.getStudents();
            Stream<Double> doubleStream = studentList.stream().map(Student::getScore);
            doubleStream.reduce(Double::sum);
        }
    
  6. 收集(最终)

        public void test3(){
            List<Student> studentList = StudentData.getStudents();
            //返回一个list
            List<Student> listStream = studentList.stream()
                    .filter(e -> e.getAge() > 18)
                    .collect(Collectors.toList());
            //返回一个Set
            Set<Student> setStream = studentList.stream()
                    .filter(e -> e.getAge() > 18)
                    .collect(Collectors.toSet());
            //返回其他的类型
        }
    
    

并行流

并行流的处理方法和Stream相同知识将stream变成了parallelStream();

参考学习

https://blog.csdn.net/wo541075754/article/details/102458705

https://blog.csdn.net/sdddlll/article/details/103551347

https://www.cnblogs.com/zhenghengbin/p/9500822.html

https://www.jianshu.com/p/ac2bcf2f9d48

以上是关于Java8特性: stream的主要内容,如果未能解决你的问题,请参考以下文章

JAVA8新特性

Java8新特性第3章(Stream API)

Java8新特性—— Stream集合运算流入门学习

java代码之美---Java8 Stream

Java8 Stream流

Java8特性详解 lambda表达式 Stream