zoukankan      html  css  js  c++  java
  • Java基础知识09--Stream API详解01

    1.Stream 介绍

    Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利

    Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

    Stream可以由数组或集合创建,对流的操作分为两种:

      (1) 中间操作,每次返回一个新的流,可以有多个。
      (2) 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

    元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到处理的结果。

    +--------------------+       +------+   +------+   +---+   +-------+
    | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
    +--------------------+       +------+   +------+   +---+   +-------+

    以上的流程转换为 Java 代码为:

    List<Integer> transactionsIds = 
    widgets.stream()
                 .filter(b -> b.getColor() == RED)
                 .sorted((x,y) -> x.getWeight() - y.getWeight())
                 .mapToInt(Widget::getWeight)
                 .sum();

    另外,Stream有几个特性:

    • stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
    • stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
    • stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

     2.Stream的创建

    Stream可以通过集合数组创建。

    1、通过 java.util.Collection.stream() 方法用集合创建流

    List<String> list = Arrays.asList("a", "b", "c");
    // 创建一个顺序流
    Stream<String> stream = list.stream();
    // 创建一个并行流
    Stream<String> parallelStream = list.parallelStream();

    2、使用java.util.Arrays.stream(T[] array)方法用数组创建流

    int[] array={1,3,5,6,8};
    IntStream stream = Arrays.stream(array);

    3、使用Stream的静态方法:of()、iterate()、generate()

    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
    
    Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
    stream2.forEach(System.out::println);
    
    Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
    stream3.forEach(System.out::println);

    streamparallelStream的简单区分: stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如筛选集合中的奇数,两者的处理不同之处:

    如果流中的数据量足够大,并行流可以加快处速度。

    除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流:

    Optional<Integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();

    3.Stream的使用

    在使用stream之前,先理解一个概念:Optional 。

    Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

    3.1 遍历/匹配(foreach/find/match)

    Stream也是支持类似集合的遍历和匹配元素的,只是Stream中的元素是以Optional类型存在的。Stream的遍历、匹配非常简单。

     案例一:forEach 循环

        public static void main(String[] args) {
            //对集合进行遍历
            List<String> asList = Arrays.asList("you","don't","bird","me","!");
            // 方式一:JDK1.8之前的循环方式
            for (String str : asList) {
                System.out.println(str);
            }
            System.out.println("---------------------2--------------------------");
            // 方式二:使用Stream的forEach方法
            asList.stream().forEach(x-> System.out.println(x));
            System.out.println("---------------------3--------------------------");
            // 方式二:使用Stream的forEach方法简写方式
            asList.stream().forEach(System.out::println);
            //注:其实在数据量小时推荐使用增强for循环,如果在大数据量(大数据分析)下可以使用新的循环
    
        }

    效果图:

    案例二:

        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
    
            // 遍历输出符合条件的元素
            list.stream().filter(x -> x > 6).forEach(System.out::println);
            // 匹配第一个
            Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
            // 匹配任意(适用于并行流)
            Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
            // 是否包含符合特定条件的元素
            boolean anyMatch = list.stream().anyMatch(x -> x < 6);
            System.out.println("匹配第一个值:" + findFirst.get());
            System.out.println("匹配任意一个值:" + findAny.get());
            System.out.println("是否存在大于6的值:" + anyMatch);
    
        }

    执行结果:

    7
    9
    8
    匹配第一个值:7
    匹配任意一个值:8
    是否存在大于6的值:true

    3.2 筛选(filter)

    筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

     案例一:筛选出Integer集合中大于7的元素,并打印出来

        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2, 9);
            Stream<Integer> stream = list.stream();
            stream.filter(x -> x > 7).forEach(System.out::println);
        }

    执行结果:

    8
    9

    案例二: 筛选员工中工资高于8000的人,并形成新的集合。 形成新集合依赖collect(收集)

    案例中使用的员工类:

    package com.hztest.domain;
    
    
    public class Person {
        private String name;  // 姓名
        private int salary; // 薪资
        private int age; // 年龄
        private String sex; //性别
        private String area;  // 地区
    
        // 构造方法
        public Person(String name, int salary, int age,String sex,String area) {
            this.name = name;
            this.salary = salary;
            this.age = age;
            this.sex = sex;
            this.area = area;
        }
        // 省略了get和set,请自行添加
    }
        public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male", "New York"));
            personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
            personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
            personList.add(new Person("Anni", 8200, 24, "female", "New York"));
            personList.add(new Person("Owen", 9500, 25, "male", "New York"));
            personList.add(new Person("Alisa", 7900, 26, "female", "New York"));
    
            List<String> fiterList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName)
                    .collect(Collectors.toList());
            System.out.print("高于8000的员工姓名:" + fiterList);
    
        }

    运行结果:

    高于8000的员工姓名:[Tom, Anni, Owen]

    3.3 聚合(max/min/count)

    maxmincount这些字眼你一定不陌生,没错,在mysql中我们常用它们进行数据统计。Java stream中也引入了这些概念和用法,极大地方便了我们对集合、数组的数据统计工作。

     案例一:获取Integer集合中的最大值。

        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);
    
            // 自然排序
            Optional<Integer> max = list.stream().max(Integer::compareTo);
            // 自定义排序
            Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1.compareTo(o2);
                }
            });
            System.out.println("自然排序的最大值:" + max.get());
            System.out.println("自定义排序的最大值:" + max2.get());
    
        }

    执行结果:

    自然排序的最大值:11
    自定义排序的最大值:11

    案例二:计算Integer集合中大于6的元素的个数。

        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
    
            long count = list.stream().filter(x -> x > 6).count();
            System.out.println("list中大于6的元素个数:" + count);
    
        }

    执行结果:

    list中大于6的元素个数:4

    参考文献:https://www.jianshu.com/p/2b40fd0765c3

    https://blog.csdn.net/mu_wind/article/details/109516995(重点推荐)

    https://blog.csdn.net/princejwg/article/details/105941009(推荐)

  • 相关阅读:
    Motion Estimation ,运动估计
    BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议) 转自CSDN:gushenghua的专栏
    BT源代码学习心得(十一):客户端源代码分析(存储管理) 转自CSDN:gushenghua的专栏
    BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) 转自CSDN:gushenghua的专栏
    BT源代码学习心得(十二):客户端源代码分析(从开始到连接建立阶段)
    BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象)
    BT源代码学习心得(十):客户端源代码分析(相关对象一览) 转自CSDN:gushenghua的专栏
    BT源代码学习心得(十四):客户端源代码分析(对等客户连接中的阻塞管理) 转自CSDN:gushenghua的专栏
    BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) 转自CSDN:gushenghua的专栏
    BT源代码学习心得(四):种子文件的生成 转自CSDN:gushenghua的专栏
  • 原文地址:https://www.cnblogs.com/luckyplj/p/15215655.html
Copyright © 2011-2022 走看看