JDK8.0相关特性-Stream(三)

JDK8.0相关特性

六、 Stream(流)
  • 流(Stream):是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。Stream提供了强大的数据集合操作功能,但是它不能保存数据,像是一个高级的Iterator。

    • 注意:
      • 集合讲的是数据(集合用于存储数据),流讲的是计算(流用于对集合中数据的操作)
      • Stream本身不能应用存储元素
      • Stream不会改变源对象
  • Stream(流)的操作三个步骤:创建Stream、中间操作、终端操作

    在这里插入图片描述

    • 创建Stream(从数据源获取):一个数据源(如集合、数组),获取一个流(Stream)

      • 获取Stream流的几种方式
      //1. 可以通过Collection 系列集合提供的stream()或是 parallelStream()
      List<String> list= new ArrayList<String>();
      Stream<String> stream1=list.stream();
      
      //2. 通过Arrays中的静态方法stream() 获取数组流
      Student[] s = new Student[10];
      Stream stream2=Arrays.stream(s);
      
      //3. 通过Stream类中的静态方法of()
      Stream<String> stream3=Stream.of("aa","bb","cc");
      
      //4. 创建无限流
      //迭代
      Stream<Integer> stream4=Stream.iterate(0,(x)-> x+2);
      stream4.forEach(System.out::println);//终端操作
      
      //自动生成
      Stream stream5=Stream.generate(()->Math.random());
      stream5.forEach(System.out::println);
      
    • 中间操作:一个中间操作链,对数据源的数据进行处理

      1. 筛选与切片中间操作:
         filter(Predicate<T> f) : 接受Lambda表达式,从流中筛选某些元素
         limit(long n): 截断流,使其元素不超过给定数量
         skip(long n):跳过流中的n个元素
         distinct():去除流中的重复元素
      
      • 案例:
      //获取年龄大于36的学生信息
         Stream stream1=stus.stream().filter((s)->s.getAge()>36);
         //stream1.forEach(System.out::println);
         
      //获取2名年龄大于36的学生信息
      Stream stream2=stus.stream().
          filter((s)->s.getAge()>36).limit(2);
      stream2.forEach(System.out::println);
      
      //跳过2名年龄大于36的之后的学生信息
      Stream stream3=stus.stream().
          filter((s)->s.getAge()>36).skip(2);
      stream3.forEach(System.out::println);
      
      //龄大于36的学生信息,要求去除内容重复的元素
      Stream stream4=stus.stream().
          filter((s)->s.getAge()>36).distinct();
      stream4.forEach(System.out::println);
      
      2.映射
        map<Function<T,R> f>:接收一个函数(Function形式的Lambda表达式)作为
           参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素,返回值类
           型为Stream<R>。
        flatMap<Function<T,Stream<R>>>:接收一个函数作为参数,将流中的每一
           个值都换成另一个流,然后把所有流连城一个流Stream<R>。
      
      * 案例1:
      
      //将集合中元素小写转换为大写
      List<String> list= Arrays.asList("aa","bb","cc");
      Stream<String> stream6=list.stream().
      map((str)-> str.toUpperCase());
      stream6.forEach(System.out::println);
      
      //获取集合(泛型为学生对象)中学生的姓名
      stus.stream().map((s)->s.getName()).
      forEach(System.out::println);
      
      -------------------------------------------------------
      //将上面List集合中所有的元素的组成字符进行打印输出
         public class TestFlagMap{
             public static void main(String[] args){
             	List<String> list= Arrays.asList("aa","bb","cc");
                 Stream<Stream<Character>> stream7=list.stream().
                                    map(TestStream::filterCharacter);
                 stream7.forEach(
                 	(stream)->stream.forEach(System.out::println)
                 );
                 list.stream().flatMap(TestStream::filterCharacter).
                     forEach(System.out::println);
             }
             public static Stream<Character> filterCharacter(String str)     {
                 List<Character> list= new ArrayList<>();
                 for (Character c:str.toCharArray()){
                     list.add(c);
                 }
                 return list.stream();
             }
         }
      
      3. 排序
         sorted(): 自然排序
         sorted(Comparator com):定制排序
      
      • 案例
      List<String> list= Arrays.asList("ff","aa","ss","bb","cc","dd");
      list.stream().sorted().forEach(System.out::println);
      
      --------------------------------------------------------------
      List<Student> stus= Arrays.asList(new Student("张三",38),
                      new Student("李四",40),
                      new Student("王五",37),
                      new Student("胡杨",35)
                      );
      
      stus.stream().sorted((s1,s2)->{
      	if(s1.getAge()==s2.getAge()){
      	return s1.getName().compareTo(s2.getName());
      } else{
      	return s1.getAge()-s2.getAge();
      }
      }).forEach(System.out::println);
      
      * 注意
      
      多个中间操作可以连接形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理,并且在终止操作时一次性全部处理,称为"惰性求值"
      
    • 终端操作(终止操作):一个终止操作,执行中间操作链,并产生结果

      • 常见的终端操作:
      1.基础终端操作
      allMatch(Predicate<T>):检查是否匹配所有的元素,返回值类型为bollean
      anyMatch(Predicate<T>):检查是否至少匹配一个元素,返回值类型为bollean
      noneMatch(Predicate<T>):检查是否没有匹配任何元素,返回值类型为bollean
      findFirst():返回第一个元素,类型为Optional<T>,利用get方法获取员孙
      findAny():返回当前流中的任意元素
      count():返回流中元素的个数,返回值类型为long
      max(Comparator<T> com):返回流中最大值,返回类为Optional
      min(Comparator<T> com):返回流中最小值
      forEach(Consumer c):内部迭代
      
      • 案例:
      List<Student> list = Arrays.asList(
                      new Student("zhangsan",38, Student.Status.Study),
                      new Student("lisi",27, Student.Status.Study),
                      new Student("tom",30, Student.Status.Sleep),
                      new Student("hanmeimei",25, Student.Status.Sleep),
                      new Student("lihua",32, Student.Status.Sleep)
                      );
      //判断年龄大于26的学生是否都在学习
      boolean r=list.stream().
      			filter((s)->s.getAge()>26).
      			allMatch(
      				(s)->s.getStatus().equals(Student.Status.Study)
      			);
      System.out.println(r);
      
      //按照年龄排序,获取排序后的第一个学生信息
      Optional<Student> o=list.stream().
          sorted((s1, s2)->s1.getAge()-s2.getAge()).findFirst();
      System.out.println(o.get());
      
      //随机获取一个睡觉学生的信息
      Optional<Student> o2=list.stream().filter(
          	(s)->Student.Status.Sleep.equals(s.getStatus())
      	).findAny();
      System.out.println(o2.get());
      
      //获取睡觉学生的个数
      long count=list.stream().filter(
               (s)>Student.Status.Sleep.equals(s.getStatus())
           ).count();
      System.out.println("睡觉学生个数:"+count);
      
      //获取学生中年龄最大的信息
      Optional<Student> o3=list.stream().max(
          (s1,s2)->s1.getAge()-s2.getAge());
      System.out.println(o3.get());
      
      //获取学生中年龄最小的信息
      Optional<Student> o4=list.stream().min(
          (s1,s2)->s1.getAge()-s2.getAge());
      System.out.println(o4.get());
      
      2.规约操作
        reduce(T identity, BinaryOperator<T> acc):将流中的数据反复结合起来,得到一个值,返回值为T类型
        reduce(BinaryOperator<T> acc):将流中元素反复结合起来,得到一个值,返回值类型为Optional<T>。
        
        注意:map和reduce的连接通常称为map-reduce模式。
      
      • 案例:
      List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);
      
      //获取集合中所有元素的加和
      Integer n = list.stream().reduce(0,(x,y)->x+y);
      System.out.println(n);
      
      -----------------------------------------------------------
      List<Student> list2 = Arrays.asList(
                  new Student("zhangsan",38, Student.Status.Study),
                  new Student("lisi",27, Student.Status.Study),
                  new Student("tom",30, Student.Status.Sleep),
                  new Student("hanmeimei",25, Student.Status.Sleep),
                  new Student("lihua",32, Student.Status.Sleep)
              );
      
      Integer sum=list2.stream().map(
          (s)->s.getAge()).reduce(0,(a1,a2)->a1+a2);
      System.out.println(sum);
      
      3.收集
        collect(Collector<T, A, R> collector):将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。(位于Stream中的方法)
        收集器常用接口和方法:
        Collector<T,A,R>:T - 元素类型;A - 中间类型;R-结果类型
        Collectors:获取收集器的工具类,其中定义大量静态方法
        	(1) toList():将流转换为List类型
        	(2) toSet():将流转换为Set类型
        	(3) counting():统计元素个数,返回值类型为long
        	(4) summarizingInt(ToIntFunction<T> f):获取int类型的总和
        	(5) averagingInt(ToIntFunction<T> f):获取int类型的平均值
        	(6) maxBy(Comparator<T> com):获取最大值,返回值类型Optional<T>
        	(7) minBy(Comparator<T> com):获取最小值
        	(8) joining()/joining(String s):字符串的拼接,返回值类型为String
        	(9) 分组操作:
        	    ① groupingBy(Function(K,T) f):将流中元素按照指定内容进行分组,转
        	    换结果为Map<T,List<K>> (注意:Map中的键是指定分组分依据内容,K是
        	    分组元素)groupingBy(Function<T,K> f,Collector<T,?,D> c):多级分组
          (10)分区操作:
              partitioningBy(Predicate<T> p):按照内容将流中元素划分为falsetrue两个区,转换结果类型为Map<Boolean,List<T>>
      
      • 案例:
      //将学生姓名存储在List集合中
      List<String> l=list2.stream().
                    map((s)->s.getName()).collect(Collectors.toList());
      l.forEach(System.out::println);
      
      //将学生姓名存储在HashSet集合中
      HashSet<String> l=list2.stream().map((s)->s.getName()).
                    collect(Collectors.toCollection(HashSet::new));
      l.forEach(System.out::println);
      
      //获取集合中所有学生的年龄总和
      int sum2=list2.stream().collect(
          Collectors.summarizingInt((s)->s.getAge()));
      
      //获取年龄最大的学生信息
      Optional<Student> s=list2.stream().collect(
          Collectors.maxBy((s1, s2)->s1.getAge()-s2.getAge()));
      System.out.println(s);
      
      //将集合中所有学生的姓名进行字符串拼接
      String s2=list2.stream().map((s1)->s1.getName()).
                  collect(Collectors.joining("-"));
      
      --------------------------分组----------------------------------
      //将集合中元素按照状态进行分组
      Map<Student.Status,List<Student>> map=list2.stream().collect(
                   Collectors.groupingBy((s3)->s3.getStatus()));
          
      //将集合中元素先按照状态分组,再按照学生年龄分组:年龄<30,返回青年,否则中年
      Map<Student.Status,Map<String,List<Student>>> map2=list2.stream().
          collect(Collectors.groupingBy(
              (s3)->s3.getStatus(),Collectors.groupingBy((s3)->{
                  if(s3.getAge()<30){
                      return "青年";
                  }else {
                      return "中年";
                  }
              })));
      
      //获取每种状态下学生的平均年龄
      Map<Student.Status,Double> map3=list2.stream().collect(
          Collectors.groupingBy((s3)->s3.getStatus(),
             Collectors.averagingDouble((s3)->s3.getAge())));
      
      //将集合中按照年龄是否大于30分成两个小组
      Map<Boolean,List<Student>> map4=list2.stream().
          collect(Collectors.partitioningBy((s3)->s3.getAge()>30));
      
      --------------------------------------------------------------
      DoubleSummaryStatistics sum2=list2.stream().collect(
          Collectors.summarizingDouble((s3)->s3.getAge()));
      System.out.println(sum2.getMax());
      System.out.println(sum2.getAverage());
      System.out.println(sum2.getCount());
      System.out.println(sum2.getMin());
      

      以上案例中的Student类:
      class Student{
          private String name;
          private Integer age;
          private Status Status;
          public Student() {}
          public Student(String name, Integer age) {
              this.name = name;
              this.age = age;
          }
          public Student(String name,Integer age,Student.Status status)     {
              this.name = name;
              this.age = age;
              Status = status;
          }
          public Student.Status getStatus() {
              return Status;
          }
          public void setStatus(Student.Status status) {
              Status = status;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
          public Integer getAge() {
              return age;
          }
          public void setAge(Integer age) {
              this.age = age;
          }
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
          public enum Status{
              Study,Play,Sleep;
          }
      }
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值