• java中的Stream类的使用


    JAVA中的Stream类用法

    简单来说,Stream就是java中用来模拟流数据的一种方式,它不是一种数据结构,也不是i一中内部存储,只负责抓去数据,也不会变更底层数据。提供的一些方法可以模拟sql进行快速的数据处理,也可以类比为大数据中的MR处理,和scala中的算子有着异曲同工的意思。

    Stream有一个特性,就是内部方法操作必须使用lambda表达式。

    一、Stream的实例化

    实例化一个Stream对象有几种方式

    1. 调用静态方法:Stream.of()

    Stream<String> stream1 = Stream.of("string", "int", "double", "long");
    
    • 1

    Stream.of()方法也可以直接把数组传进去

    String[] str = {"boolean", "map", "array"};
    Stream<String> stream2 = Stream.of(str);
    
    • 1
    • 2

    Stream.of()内部其实调用的是Arrays类中的一个方法,具体源码如下:

    @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
      public static<T> Stream<T> of(T... values) {
      return Arrays.stream(values);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 调用Arrays类中的方法Arrays.stream()

    因为Stream.of()是调用的Arrays.stream(),那么这个方法也可以返回一个Stream类的对象

    Stream<String> stream3 = Arrays.stream(str);
    
    • 1

    3. stream()

    集合类型可以调用stream()方法返回一个Stream对象

    List<String> list = Arrays.asList("struct", "float");
    Stream<String> stream4 = list.stream();
    
    • 1
    • 2

    二、Stream中的方法

    1. Stream流的转换

    • 数组可以通过Stream.of()转换为Stream

    • list可以通过stream()转换为Stream

    • Stream可以通过collect()转换为其他类型

      • 转换为list或者set

        List<String> list1 = stream1.collect(Collectors.toList());
        Set<String> set1 = stream1.collect(Collectors.toSet());
        List<String> list2 = stream1.collect(Collectors.toCollection(ArrayList :: new));
        
        • 1
        • 2
        • 3
      • 转换为string

        String str2 = stream1.collect(Collectors.joining());
        
        • 1
      • 注意:每个stream只能使用1次,佛则会有非法状态的异常

        java.lang.IllegalStateException: stream has already been operated upon or closed
        
        • 1

    2. filter的使用

    拿集合举例,如果要过滤一个集合中的元素,传统应该怎么做?

    for (String s : list) {
      if (!"string".equals(s)){
        System.out.println(s);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用Stream流时候

    stream1.filter(str -> !"string".equals(str)).collect(Collectors.toList()).forEach(System.out::println);
    
    • 1

    除此之外,如果没有找到,还可以配合findAny和orElse方法处理

    System.out.println(stream1.filter("string"::equals).findAny().orElse("无过滤"));
    
    • 1

    还可以配合mapToInt和sum进行计算

    Stream<Integer> streamInt = Stream.of(1, 2, 3, 4);
    int res = streamInt.filter(num -> num > 2).mapToInt(n -> n).sum();
    
    • 1
    • 2

    3. map的使用

    map的使用就是做基本转换

    比如:全部转换为大写

    stream1.map(str -> str.toUpperCase()).collect(Collectors.toList()).forEach(System.out::println);
    
    • 1

    比如:转换为长度

    stream1.map(str -> str.length()).collect(Collectors.toList()).forEach(System.out::println);
    
    • 1

    4. flatmap的使用

    扁平化处理,可以对元素进行打散操作

    List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.collect(Collectors.toList()).forEach(System.out::println);
    
    • 1
    • 2
    • 3

    还可以配合其他的处理,比如filter,过滤出带有“ , ”的字符串

    List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.filter(str -> str.matches(".*,.*")).forEach(System.out::println);
    
    • 1
    • 2
    • 3

    5. limit的使用

    如果是模拟sql,那么limit是必不可少的

    ist<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.limit(2).forEach(System.out::println);
    
    • 1
    • 2
    • 3

    只输出两个结果,limit方法是取前n个数据,那么skip是去除前n个数据,那么两个可以一同使用

    List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.limit(2).skip(1).forEach(System.out::println);
    
    • 1
    • 2
    • 3

    6. Sorted的使用

    有了limit,那怎么能少了sort呢,sort就是排序了

    List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.sorted().forEach(System.out::println);
    
    • 1
    • 2
    • 3

    如果不指定排序方式,会默认升序排序

    List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.sorted((a,b) -> -(a.length()-b.length())).forEach(System.out::println);
    
    • 1
    • 2
    • 3

    7. peek的使用

    peek会对每个元素执行操作并返回一个新的Stream

    List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
    Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
    stream.filter(str -> str.length()>5).peek(ele -> System.out.print(ele + " --> "))
      .map(String::toUpperCase).peek(System.out::println).forEach(System.out::println);
    
    • 1
    • 2
    • 3
    • 4

    8. max/min/distinct的使用

    得到最大最小以及去重之后的结果

    System.out.println(stream.mapToInt(String::length).max());
    System.out.println(stream.mapToInt(String::length).min());
    System.out.println(stream.mapToInt(String::length).distinct());
    
    • 1
    • 2
    • 3

    9. match的使用

    • allMatch:全部字符匹配则返回true
    • anyMatch:任何字符匹配则返回true
    • noneMatch:没有一个元素符合返回true
    System.out.println(stream.allMatch("hello"::equals));
    System.out.println(stream.anyMatch("hello"::equals));
    System.out.println(stream.noneMatch("hello"::equals));
    
    • 1
    • 2
    • 3

    10. reduce的使用

    reduce类似于一个聚合函数,对一个组内的数据进行处理

    • 字符串连接

      System.out.println(stream.reduce("", String::concat));
      
      • 1
    • 获取最小值

      stream.map(String::length).reduce(Integer.MAX_VALUE, Integer::min);
      
      • 1
    • 求和

      stream.map(String::length).reduce(Integer::sum);
      stream.map(String::length).reduce(1,Integer::sum);
      
      • 1
      • 2

    11. iterate的使用

    类似于reduce,可以传入第一个参数为种子值,也可以说是初始值,然后第二个参数传入迭代值

    Stream.iterate(3, n -> n-2).limit(10).forEach(System.out::println);
    
    • 1

    12. supplier的使用

    类似于一个底层的类,可以自定义流计算方法

    class ownSupplier implements Supplier<String>{
      Random random = new Random();
        @Override
        public String get() {
    
          return random.nextInt(10) + ": random";
    }
    
    Stream.generate(new ownSupplier()).limit(5).forEach(System.out::println);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    13. groupingBy/partitioningBy的使用

    • groupingBy:分组排序

      Map<String, List<String>> group = Stream.generate(new ownSupplier()).limit(5)
        .collect(Collectors.groupingBy(str -> str.split(":")[0]));
      
      • 1
      • 2
    • partitioningBy:分区排序

      Map<Boolean, List<String>> partition = Stream.generate(new ownSupplier()).limit(5)
      	.collect(Collectors.groupingBy(str -> str.length() > 4));
      
      • 1
      • 2

    14. summaryStatistics的使用

    summaryStatistics方法给出了流的基本信息,比如最大值、最小值、汇总值等,类似于sql中的max、min、xount等

    Stream<Integer> istream = Stream.of(1, 2, 3, 4, 5, 6);
    IntSummaryStatistics sumStream = istream.mapToInt(n -> n).summaryStatistics();
    sumStream.getMax();
    sumStream.getMin();
    sumStream.getSum();
    sumStream.getAverage();
    sumStream.getCount();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    云原生之容器化:Docker三剑客之Docker Machine
    软考历年问题总结
    C++_linux下_非阻塞键盘控制_程序暂停和继续
    RNA修饰质谱检测|dextran-siRNA 葡聚糖化学偶联DNA/RNA|siRNA-PLGA聚乳酸-羟基乙酸共聚物修饰核糖核酸
    关于Dubbo传输协议与上传文件的坑
    注解与自定义注解
    洛谷P1102 A-B 数对题解
    【面试高频题】难度 3/5,可直接构造的序列 DP 题
    基于 51 的点阵屏显示 8*8 点阵仿真实验
    OCP Java17 SE Developers 复习题06
  • 原文地址:https://blog.csdn.net/weixin_46429290/article/details/126090847