• java Stream操作


    java stream操作

    Stream是什么

    Stream又称为流,可以将集合转换为一种流,对集合中的每个元素进行一系列的流式操作,流并不存储元素,对流的操作也不会修改数据源

    数据源 ------转换为--》流----》进行中间操作----》终止操作

    多个中间操作可以连接起来形成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何处理,在终止操作时一次性全部处理

    转化为流

    使用stream()或者parallelStream()方法将集合转为流

    生成流

    可以使用Stream.generate来生成流,产生一个无限流,通过反复调用函数来生成流

    Stream stream = Stream.generate(()->"Echo");
    • 1

    也可以使用Stream.of来生成Stream,产生一个给定值的流

    Stream stream1 = Stream.of("hello""java8");
    • 1

    可以用Stream.empty生成一个不包含任何元素的流

    Stream empty = Stream.empty();
    • 1

    可以使用Arrays.stream根据数据来生成流

    Stream stream2 = Arrays.stream(new String[]{"hello""java8"});
    • 1

    中间操作

    中间操作是惰性求值的,只进行描述Stream,而不产生新的集合

    筛选
    filter

    过滤操作,只返回为true(满足Predicate断言条件)的数据

    // filter方法接收的是Predicate
    Stream filter(Predicatesuper T> predicate);
    • 1
    /**
    * filter  接收lambda,从流中排除某些元素
    */

    public static void testFilter(){
      // 中间操作
      // 使用的Predicate   boolean test(T t);
      Stream stream = list.stream()
        .filter(e ->
                {
                  System.out.println("filter中间操作");
                  return e.equals("张三");
                }
               );
      // 这时中间操作还没有执行执行
      System.out.println("----中间操作结束----");
      //终止操作:一次执行全部操作
      stream.forEach(
        System.out::println
      );
    }
    • 1
    distinct

    去重

    /**
    * distinct 筛选,通过流所生成元素的hashCode()和equals()方法去重
    */

    public static void testDistinct(){
      list.stream().distinct().forEach(System.out::println);
    }
    • 1
    切片
    limit

    返回前n个元素

    /**
    * limit 截断流,使其元素不超过给定数量
    */

    public static void testLimit(){
      list.stream().limit(2).forEach(System.out::println);
    }
    • 1
    skip

    去除(跳过)前n个元素

    /**
    * skip 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回空流
    */

    public static void testSkip(){
      list.stream().skip(2).forEach(System.out::println);
    }
    • 1
    public static void testLimitAndSkip(){
      System.out.println("--------先limit再skip---------");
      list.stream().limit(2).skip(1).forEach(System.out::println);
      System.out.println("--------先skip再limit---------");
      list.stream().skip(1).limit(2).forEach(System.out::println);
    }
    • 1

    注意:在limit和skip搭配使用的时候,两个的顺序不同会导致结果不同

    • 先进行limit,再进行skip时,会选择前两个数据,然后再跳过第一个数据,只会筛选出一条数据
    • 先进行skip,再进行limit时,会先跳过一条数据,在选择剩下数据的前两条,最终会筛选出两条数据
    排序
    sorted

    排序可以有两种排序方式,第一种是进行排序的类要实现Comparable接口,第二种是在自己实现一个Comparator接口

     /**
     * sorted()自然排序  Comparable 所要排序的类必须实现Comparable接口
     */

    public static void test(){
      list.stream().map(User::getAge).sorted().forEach(System.out::println);
    }

    /**
    * sorted(Comparator com) 定制排序(Comparator)
    */

    public static void test1(){
      list.stream().sorted(
        (o1, o2) -> {
          if(o1.getAge() > o2.getAge()){
            return -1;
          }
          return 0;
        }
      ).forEach(System.out::println);
    }
    • 1
    映射
    map

    转换功能,将mapper应用于当前流中的所有元素所产生的结果,其将一种类型的值转换成了另一种类型

    // map方法接收的参数为Function接口
     Stream map(Functionsuper T, ? extends R> mapper);
    • 1
    /**
    * map 接收lambda,将元素转换为其他形式或提取信息。接收一个函数作为函数,
    * 该函数会被应用到每个元素上,并将其映射成一个新的元素
    *
    * 如果函数返回的是一个流的话,使用map会使得流里存储着多个流
    */

    public static void testMap(){
      // 使用Function  R apply(T t);
      list.stream().map(User::getAge).forEach(System.out::println);
    }
    • 1
    flatmap

    将多个Stream合并成一个Stream,将mapper应用于当前流中所有元素所产生的结果连接到一起(每一个结果都是一个流)

    // flatMap方法接收的参数为Function接口
     Stream flatMap(Functionsuper T, ? extends Stream> mapper);
    • 1
    /**
    * flatMap  接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
    *
    * 如果函数返回的是一个流,使用flatMap会使得函数返回的流中的元素放到一个流中
    */

    public static void testFlatMap(){
      // 要求Function  R apply(T t);中返回值是一个Stream流
      List add = new ArrayList<>();
      add.add("添加元素");
      List strings = list.stream().map(User::getName).collect(Collectors.toList());
      strings.stream().flatMap(
        TestStreamApi1::joinStream
      ).forEach(System.out::println);
    }
    • 1

    终止操作

    allMatch

    流中所有元素都要匹配给定的条件为true,否则为false 相当于且

    /**
    * allMatch测试
    */

    public static void testAllMatch(){
      boolean isSex = list.stream().allMatch(
        l -> l.getSex() == 0
      );
      System.out.println(isSex);
    }
    • 1
    anyMatch

    流中有任意一条数据匹配给定的条件为true,否则为false 相当于并

    /**
    * anyMatch测试
    */

    public static void testAnyMatch(){
      boolean isSex = list.stream().anyMatch(
        l -> l.getSex() == 0
      );
      System.out.println(isSex);
    }
    • 1
    noneMatch

    流中所有的数据都不匹配给定条件时为true,否则为false 相当于非

    /**
    * noneMatch测试
    */

    public static void testNoneMatch(){
      boolean isSex = list.stream().noneMatch(
        l -> l.getSex() == 0
      );
      System.out.println(isSex);
    }
    • 1
    findFirst

    找到第一个元素

    /**
    * findFirst测试
    */

    public static void testFindFirst(){
      User user = list.stream().sorted(
        ((o1, o2) -> {
          if(o1.getAge() > o2.getAge()){
            return -1;
          } else if(o1.getAge() < o2.getAge()){
            return 1;
          }
          return 0;
        })
      ).findFirst().get();
      System.out.println(user);
    }
    • 1
    findAny

    找到其中任意一个元素

    /**
    * findAny测试
    */

    public static void testFindAny(){
      User user = list.stream().filter(
        l -> l.getSex() == 0
      ).findAny().get();
      System.out.println(user);
    }
    • 1
    count

    返回流中元素的数量

    /**
    * count测试
    */

    public static void testCount(){
      long count = list.stream().count();
      System.out.println(count);
    }
    • 1
    max

    返回流中根据比较之后的最大值元素

    // max方法接收的是Comparator接口
    Optional max(Comparatorsuper T> comparator);
    • 1
    /**
    * max测试
    */

    public static void testMax(){
      User user = list.stream().max(
        ((o1, o2) -> {
          if(o1.getAge() > o2.getAge()){
            return 1;
          } else if(o1.getAge() < o2.getAge()){
            return -1;
          }
          return 0;
        })
      ).get();
      System.out.println(user);
    }
    • 1
    min

    返回流中根据比较之后的最小值元素

    // min方法接收的是Comparator接口
    Optional min(Comparatorsuper T> comparator);
    • 1
    /**
    * min测试
    */

    public static void testMin(){
      User user = list.stream().min(
        ((o1, o2) -> {
          if(o1.getAge() > o2.getAge()){
            return 1;
          } else if(o1.getAge() < o2.getAge()){
            return -1;
          }
          return 0;
        })
      ).get();
      System.out.println(user);
    }
    • 1

    归约和收集

    归约reduce

    使用reduce来进行运算,从一组值中生成一个值

    像count()、max()、min()、sum()这些内部其实也是使用的reduce

    // reduce方法接收的是BinaryOperator接口(二元运算操作)  
    Optional reduce(BinaryOperator accumulator);
    • 1
    /**
    * 归约  将流中元素反复结合起来,得到一个值
    * reduce(T identity, BinaryOperator accumulator) /BinaryOperator accumulator/U identity,
    *                  BiFunction accumulator,
    *                  BinaryOperator combiner
    */

    public static void testReduce(){
      List list = Arrays.asList(1,2,3,4,5,6,7,8,9);
      // BinaryOperator  二元运算   R apply(T t, U u);
      int sum = list.stream().reduce((x, y) -> x+y).get();
      System.out.println(sum);
    }
    • 1
    收集collect

    根据不同的收集器collect(Collectors.toList())、collect(Collectors.toSet())来返回不同的集合

    /**
    * 收集 collect -- 将流转换为其他形式 接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
    */

    public static void testCollect(){
      // Collector是一个接口  有一个Collectors提供了各种转换方式
      List strings = list.stream().map(User::getName).collect(Collectors.toList());
      System.out.println(strings);
    }
    • 1
    数据汇总

    使用summingInt可以获取总和

    Integer sum = list.stream().collect(Collectors.summingInt(User::getAge));
    System.out.println(sum);
    • 1

    使用averagingInt可以计算平均值

    Double average = list.stream().collect(Collectors.averagingInt(User::getAge));
    System.out.println(average);
    • 1

    使用summarizingInt可以获取个数、总和、平均值、最大值和最小值

    IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(User::getAge));
    // IntSummaryStatistics{count=6, sum=117, min=8, average=19.500000, max=30}
    System.out.println(summaryStatistics);
    • 1
    连接字符串

    joining用于连接字符串

    String join = list.stream().map(User::getName).collect(Collectors.joining(","));
    System.out.println(join);
    • 1
    数据分组

    collect还可以对数据进行分组

    Map> collect = adUnits.stream().collect(Collectors.groupingBy(AdUnit::getAd_campaign_id,
            Collectors.mapping(AdUnit::getId, Collectors.toList())));
    • 1

    groupingBy收集器接受一个分类函数,用来对数据分组

    数据分区

    partitioningBy用于数据分区

    Map> join = list.stream().collect(Collectors.partitioningBy(user -> user.getSex() == 0));
    // {false=[User{id=2, name='李四', age=20, sex=1}, User{id=4, name='赵六', age=25, sex=1}], true=[User{id=1, name='张三', age=18, sex=0}, User{id=3, name='王五', age=16, sex=0}, User{id=5, name='张三', age=30, sex=0}, User{id=6, name='张三', age=8, sex=0}]}

    System.out.println(join);
    • 1

    分区就是分组的一个特殊情况

    Optional的使用

    当初java8打着去除空指针的旗号推出了Optional,但是很多人用起来发现其实和判断是否为null没什么区别

    其实有效地使用Optional的关键是要使用这样的方法:它的值不存在的情况下产生一个可替代物,而只有在值存在的情况下才会使用这个值

    // 提供一个默认值,在Optional为空的时候使用默认值
    public T orElse(T other)
    // 提供一个默认值,在Optional为空的时候使用默认值(调用other来产生默认值)
    public T orElseGet(Supplier other)
    // 提供一个默认值,在Optional为空的时候抛出异常(调用exceptionSupplier来产生异常)
    public  T orElseThrow(Supplier exceptionSupplier) throws X
    // 如果Optional不为空,将值传给consumer
    public void ifPresent(Consumersuper T> consumer)

    // 产生该Optional的值传递给mapper后的结果,只要这个Optional不为空且结果不为null,否则产生一个空Optional
    public Optional map(Functionsuper T, ? extends U> mapper)
    • 1

    而对于有些人总是使用optional.isPresent()来判断是不是空,其实和之前判断value != null没什么区别,这种情况使用Optional没有任何好处

    [https://zhhll.icu/2020/java基础/java8/1.java Stream操作/](https://zhhll.icu/2020/java基础/java8/1.java Stream操作/)

    本文由 mdnice 多平台发布

  • 相关阅读:
    java版直播商城平台规划及常见的营销模式 电商源码/小程序/三级分销+商城免费搭建
    简单8位CPU设计verilog微处理器,源码/视频
    k8s快速查看pod对应的容器
    Spring框架-AspectJ配置文件
    【Java基础】Math类、System类、toString方法、equals方法及冒泡排序实现
    java之流程控制
    Springboot毕设项目保险理赔管理系统312z6(java+VUE+Mybatis+Maven+Mysql)
    【电路理论】ArcGIS pro运行Linkage map3.0
    STM32MPU6050角度的读取(STM32驱动MPU6050)
    HTTP协议的不同版本及其新特性
  • 原文地址:https://blog.csdn.net/Lxn2zh/article/details/134457285