zoukankan      html  css  js  c++  java
  • 关于Stream的使用

    引言

      Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

    转自:https://blog.csdn.net/y_k_y/article/details/84633001

    特点:

            1 . 不是数据结构,不会保存数据。

            2. 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)

            3. 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。

    创建流

    // 获取顺序流
    Stream stream = new ArrayList().stream(); 
    // 获取并行流
    Stream parallelStream = new ArrayList().parallelStream(); 
    // 数组转成流
    Integer[] nums = {1,2,3};
    Stream<Integer> streamArray = Arrays.stream(nums);

    赋值

    // of方法直接赋值
    Stream<Integer> stream1 = Stream.of(1,2,3,4,5);
    stream1.forEach(System.out::println); // 1 2 3 4 5
    // iterate生成生成无限顺序有序流,主要作用是抽象迭代逻辑
    Stream<Integer> stream2 = Stream.iterate(2, x -> x * 2).limit(5);
    stream2.forEach(System.out::println); // 2 4 8 16 32
    // generate生成无限顺序无序流,其中每个元素由提供的供应商生成。这适用于生成恒定流,随机元素流等。
    Stream<Integer> stream3 = Stream.generate(new Random()::nextInt).limit(2);
    stream3.forEach(System.out::println); //15356208 -2042159

    筛选与切片

    filter:过滤流中的某些元素 limit(n):获取n个元素 skip(n):跳过n元素 distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10};
    Stream<Integer> streamArray = Arrays.stream(nums);
    Stream<Integer> result = streamArray
            .distinct()  // 去重 1 2 3 4 5 6 7 8 9 10
            .filter(i -> (i > 2)) // 筛选出值>2的元素 3 4 5 6 7 8 9 10
            .skip(2) // 跳过前2个元素 5 6 7 8 9 10
            .limit(4); // 获取前4个元素 5 6 7 8

    映射

    map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素

    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10};
    Stream<Integer> streamArray = Arrays.stream(nums);
    List<String> strings = streamArray
            .map(String::valueOf) // 通过String.valueOf()方法将各个元素转为字符串
            .collect(Collectors.toList()); // 将流转为List集合

    flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

    Stream<String> streamArray2 = Stream.of("1.2.3", "4.5.6", "7.8.9");
    List<String> result = streamArray2
            .flatMap(s -> Arrays.stream(s.split("\."))) //将流中的每个值都换成另一个流,然后分割
            .collect(Collectors.toList());
    // 1 2 3 4 5 6 7 8 9

    排序

    sorted():自然排序,流中元素需实现Comparable接口

    List<String> list = Arrays.asList("a", "d", "c", "b", "x");
    List<String> result = list.stream()
      .sorted()
      .collect(Collectors.toList());
    // a b c d x

    sorted(Comparator com):定制排序,自定义Comparator排序器

    Person s1 = new Person("aa", 10);
    Person s2 = new Person("bb", 20);
    Person s3 = new Person("aa", 30);
    Person s4 = new Person("dd", 40);
    List<Person> personList = Arrays.asList(s1, s2, s3, s4);
    //自定义排序:先按姓名升序,姓名相同则按年龄升序
    personList.stream().sorted(
          (o1, o2) -> {
               if (o1.getName().equals(o2.getName())) {
                   return o1.getAge() - o2.getAge();
              } else {
                   return o1.getName().compareTo(o2.getName());
              }
          }
    ).forEach(person -> System.out.println(person.getName()));
    
    

    消费

    peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值

    Person s1 = new Person("aa", 10);
    Person s2 = new Person("bb", 20);
    Person s3 = new Person("aa", 30);
    Person s4 = new Person("dd", 40);
    List<Person> personList = Arrays.asList(s1, s2, s3, s4);
    ​
    personList.stream()
            .peek(person -> person.setAge(100))
            .forEach(person -> System.out.println(person.getName()+":"+person.getAge()));

    匹配

    allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false

    List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
    // 里面的元素是否都满足>10这个条件
    boolean result = integers.stream().allMatch(i -> i > 10); // false

    noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    // 里面的元素是否都 不 满足>10这个条件
    boolean result = list.stream().noneMatch(i -> i > 10); // true

    anyMatch:接收一个 Predicate 函数,只要流中存在元素满足该断言则返回true,否则返回false

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
    // 里面的元素是否存在满足>10这个条件
    boolean result = list.stream().anyMatch(i -> i > 10); // true

    findFirst:返回流中第一个元素

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
    // Optional对象常用于解决空指针问题
    Optional<Integer> optional = list.stream().findFirst();
    System.out.println(optional.get()); // 1

    count:返回流中元素的总个数

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
    Long result = list.stream().count();
    System.out.println(result); // 6

    max:返回流中元素最大值

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
    Integer max = list.stream().max(Integer::compareTo).get(); // 11

    min:返回流中元素最小值

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
    Integer min = list.stream().min(Integer::compareTo).get(); // 1

    reduce

    Optional<T> reduce(BinaryOperator<T> accumulator)

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
    Optional<Integer> optional = list.stream().reduce((x1, x2) -> x1 + x2);
    System.out.println(optional.get()); // 21(为流中元素的和)
    // 等效于
    // Optional<Integer> optional = list.stream().reduce(Integer::sum);

    T reduce(T identity, BinaryOperator<T> accumulator)

    identity:返回实例 accumulator:累加器

    String[] strings = {"a", "b", "c", "d", "e"};
    String reduce2 = Arrays.stream(strings).reduce("", (a, b) -> {
        if (!"".equals(a)) {
            return a + "|" + b;
        } else {
            return b;
        }
    });
    /**
     * 执行流程:
     * 第一个元素identity的值为"",因此a的初始值为"",b的初始值为流中第一个元素"a"
     * 第一次执行之后得到结果"a",然后执行结果的值赋给a,流中第二个元素的值"b"赋给b
     * 第二次执行之后得到结果"a|b",然后以此类推
     */
    System.out.println(reduce2); // a|b|c|d|e

    reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)

    identity:返回实例 accumulator:累加器 combiner:组合器

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
    Integer v2 = list.stream().reduce(0,
            (x1, x2) -> {
                System.out.println("stream accumulator: x1:" + x1 + "  x2:" + x2);
                return x1 - x2;
            },
            // 第三个参数---参数的数据类型必须为返回数据类型,改参数主要用于合并多个线程的result值
            //(Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result)
            (x1, x2) -> {
                System.out.println("stream combiner: x1:" + x1 + "  x2:" + x2);
                return x1 * x2;
            });
    System.out.println(v2); // -300

     

     

  • 相关阅读:
    Oracle expdp impdp中 exclude/include 的使用
    Oracle表空间迁移Move Tablespace
    m2ewtp的作用
    有意思的排序算法合并排序
    有意思的排序算法插入排序
    equals与“==”之惑
    简化的打印语句静态导入
    有意思的排序算法堆排序
    博客开篇语
    MySQL 整理笔记 张大哥
  • 原文地址:https://www.cnblogs.com/kzyuan/p/14279350.html
Copyright © 2011-2022 走看看