美文网首页
Java8-Stream流式计算

Java8-Stream流式计算

作者: 徒手說梦话 | 来源:发表于2020-09-11 14:21 被阅读0次

    什么是Stream流式计算

    大数据:存储 + 计算

    集合、MySQL 本质就是存储东西的;

    计算都应该交给流来操作!

    Stream是对集合功能的增强,它提供了各种非常便利、高效的聚合操作,可以大批量数据操作,同时再结合Lambda表达式,就可以极大的提高编程效率。

    Stream的API提供了串行和并行两种模式进行操作数据。

    Stream操作分为中间操作或者最终操作两种:

    • 中间操作,返回Stream本身,这样就可以将多个操作依次串起来例如,map、flatMap、filter、distinct、sorted、peek、limit、skip、parallel、sequential、unordered
    • 最终操作,返回一特定类型的计算结果例如,forEach、forEachOrdered、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator
    public class User {
        private Integer id;
        private String name;
        private Integer age;
        // get、set
        // 有参、无参构造方法
        // tostring
    }
    
    package com.kuang.stream;
    import java.util.Arrays; import java.util.List;
    /** 
    * 题目要求:一分钟内完成此题,只能用一行代码实现! * 现在有5个用户!筛选: 
    * 1、ID 必须是偶数 
    * 2、年龄必须大于23岁 
    * 3、用户名转为大写字母 
    * 4、用户名字母倒着排序
    * 5、只输出一个用户!
    */
    public class Test {   
        public static void main(String[] args) {   
            User u1 = new User(1,"a",21);        
            User u2 = new User(2,"b",22);    
            User u3 = new User(3,"c",23);       
            User u4 = new User(4,"d",24);      
            User u5 = new User(6,"e",25);      
            // 集合就是存储      
            List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
            // 计算交给Stream流      
            // lambda表达式、链式编程、函数式接口、Stream流式计算     
            list.stream()         
                .filter(u->{return u.getId()%2==0;})    
                .filter(u->{return u.getAge()>23;})        
                .map(u->{return u.getName().toUpperCase();})   
                // 这个只是字符串比较 如果是对象比较需要另一种方式
                .sorted((uu1,uu2)->{return uu2.compareTo(uu1);})         
                .limit(1)
                .forEach(System.out::println); 
        } 
    }
    

    Stream的操作,看起来很像生产车间的流水线作业:

    image-20200908193536299.png
    常用方法:
    • iterator:返回迭代器对象

    • forEach:将调Stream中的每个元素,交给一个Consumer函数处理

      public class Test {
          public static void main(String[] args{
                Stream<String> stream = Stream.of("hello","world","briup");
                stream.forEach(System.out::println);    
          }
      }
      
    • count:统计流中的元素数,并返回结果

      public class Test {
          public static void main(String[] args{
        Stream<String> stream = Stream.of("hello","world","briup");
              System.out.println(stream.count());    
          }
      }
      
    • max:返回流中基于comparator所指定的比较规则,比较出的最大值

      image-20200908201255836.png
    • toArray:使用调用流中的元素,生成数组返回

    • filter:过滤

      public static void filter(){
          // 通过流将字符串转换成Stream格式的集合
          Stream<String> java = Stream.of("Java", "Python", "PHP");
          // 将包含字符串P的字符串筛选出来,并打印结果
          java.filter(str -> str.contains("P")).forEach(str -> System.out.println(str));
      }
      
    • distinct:去重

      System.out.println("所有user的年龄集合");
      List<Integer> userAgeList = list.stream().map(User::getAge).distinct().collect(Collectors.toList());
      System.out.println("userAgeList = " + userAgeList);
      
      所有user的年龄集合
      userAgeList = [``10``, ``12``, ``15``, ``25``, ``16``, ``14``, ``17``]
      
    • Collectors.toList():返回一个 Collector ,它将输入元素 List到一个新的 List

    • limit:limit返回包含前n个元素的流,当集合大小小于n时,则返回实际长度

      public static void filter(){
          // 通过流将字符串转换成Stream格式的集合
          Stream<String> java = Stream.of("Java", "Python", "PHP");
          // 将包含字符串P的字符串筛选出来,只输出一个
          java.filter(str -> str.contains("P")).limit(1).forEach(str -> System.out.println(str));
      }
      
    • sorted:sorted要求待比较的元素必须实现comparator接口

      • Comparator接口里面有一个compare方法,方法有两个参数T o1和T o2,是泛型的表示方式,分别表示待比较的两个对象

        • o1大于o2,如果返回正整数,表示参数o1大于o2
        • o1等于o2,返回0
        • o1小于o2,如果返回负整数,表示参数o1小于o2
        import java.util.Comparator;
        
        public class StudentComparator implements Comparator<StudentBean>{
        
        
            public int compare(StudentBean o1, StudentBean o2) {
        
                // 返回负数 说明比较器认为传进来得参数o1比o2小,所以o1在o2前面
                // 实际上从我们角度o1比o2大
                // 但是比较器只看返回得结果去判断o1是否大于o2从而进行升序降序
                if(o1.getScore() > o2.getScore()){
                    return -1;
                }else if(o1.getScore() < o2.getScore()){
                    return 1;
                }
                return 0;
            }
        }
        
    • map:映射

      假设我们希望筛选出所有专业为计算机科学的学生姓名,那么我们可以在filter筛选的基础之上,通过map将学生实体映射成为学生姓名字符串

      List<String> names = students.stream()
          .filter(student -> "计算机科学".equals(student.getMajor()))
          .map(Student::getName).collect(Collectors.toList());
      

      除了上面这类基础的map,java8还提供了mapToDouble(ToDoubleFunction mapper)mapToInt(ToIntFunction mapper)mapToLong(ToLongFunction mapper),这些映射分别返回对应类型的流,java8为这些流设定了一些特殊的操作,比如我们希望计算所有专业为计算机科学学生的年龄之和,那么我们可以实现如下:

      int totalAge = students.stream()
                          .filter(student -> "计算机科学".equals(student.getMajor()))
                          .mapToInt(Student::getAge).sum();
      
      
    • 调用串行Stream的parallel()方法,可以将其转换并行Stream

    • flatMap:flatMap与map的区别在于 flatMap是将一个流中的每个值都转成一个个流,然后再将这些流扁平化成为一个流

      举例说明,假设我们有一个字符串数组

      String[] strs = {"java8", "is", "easy", "to", "use"};

      我们希望输出构成这一数组的所有非重复字符,那么我们可能首先会想到如下实现:

      List<String[]> distinctStrs = Arrays.stream(strs)
                                    // 映射成为Stream<String[]>
                                      .map(str -> str.split(""))  
                                      .distinct()
                                      .collect(Collectors.toList());
      

      在执行map操作以后,我们得到是一个包含多个字符串(构成一个字符串的字符数组)的流,此时执行

      distinct操作是基于在这些字符串数组之间的对比,所以达不到我们希望的目的,此时的输出为:

      [j, a, v, a, 8]
      [i, s]
      [e, a, s, y]
      [t, o]
      [u, s, e]
      
    • 方法 说明
      filter 元素过滤,对Stream对象按照指定的Predicate进行过滤,返回的Strema对象中仅包含满足条件的元素
      map [mapToInt] [mapToLong] [mapToDouble] 元素一对一转换,使用传入的Function对象对Stream中所有元素进行映射处理,返回的Stream对象中的元素为原元素处理后的结果
      flatMap (flatMapToInt) (flatMapToLong) (flatMapToDouble) 元素一对多转换,对Stream对象中的所有元素进行操作,每个元素会有一个或多个结果,然后将所有的元素组合成一个统一的Stream并返回
      distinct 元素去重,返回去重后的Stream对象
      sorted [sorted(Comparator<? super T> comparator)] 元素排序,返回排序后的Stream对象
      limit 元素截取,返回有限个元素组成新的Stream对象
      skip 元素跳过,抛弃前指定个元素后,使用剩下的元素组成新的Stream对象返回
      peek 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数即引用的方法,当Stream每个元素被消费的时候都会先执行新Stream给定的方法

      distinct只有对于一个包含多个字符的流进行操作才能达到我们的目的,即对Stream<String>进行操作。

      此时flatMap就可以达到我们的目的:

      List<String> distinctStrs = Arrays.stream(strs)
            // 映射成为Stream<String[]>
            .map(str -> str.split(""))  
            // 扁平化为Stream<String>
            .flatMap(Arrays::stream)  
            .distinct()
            .collect(Collectors.toList());
      

      flatMap将由map映射得到的Stream<String[]>,转换成由各个字符串数组映射成的流Stream<String>,再将这些小的流扁平化成为一个由所有字符串构成的大流Steam<String>,从而能够达到我们的目的。

    相关文章

      网友评论

          本文标题:Java8-Stream流式计算

          本文链接:https://www.haomeiwen.com/subject/nbjyektx.html