Stream流的使用

Stream流的使用

本篇主要讲解JDK8中 Stream流的使用, 包括如何 筛选 、切片、映射 、查找、匹配 、归约 等等 每个类型都会有对应的案例 简单易懂

 1.Stream的概念

 Stream API是JDK8新添加的处理集合的关键组件,这里的Stream流和I/O流不同,Stream是对集合对象功能的增强,它专注对集合对象提供各种便利的操作,只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,Stream会隐式地在内部进行遍历,做出相应的数据转换

 2.Stream流的创建

  2.1 从集合创建

     List<Integer> list = new ArrayList<>();
    //1.从集合创建流
    list.stream();
    list.parallelStream();
  2.2 从数组创建

    //Arrays的静态方法 stream 
     Arrays.stream(new int[] {1, 2, 3,});
  2.3 创建数字流

    //IntStream流 
       int intarr[] = {1,2,3};
       IntStream.of(1,2,3);
    IntStream.of(intarr);
    //LongStream流
    long longarr[] = {1L , 2L , 3L};
    LongStream.of(longarr);
  2.4 创建无限流

     //通过Random的 ints longs doubles 创建一个无限流  一般要限制个数 通过 limit是限制个数
    new Random().ints().limit(10).forEach((i) -> System.out.println(i));
    new Random().longs();
    new Random().doubles();
  2.5 自己创建Stream


    通过 Stream.generate(Supplier<T> s) 自己去实现Supplier 函数式接口,去提供数据
    //如下 通过Random去提供
    Random random = new Random();
    Stream.generate(() -> random.nextInt()).limit(20).forEach((i) -> System.out.println(i));
    //通过 Stream的 of        
    Stream.of("Hello" , "Stream")

 3.Stream提供的常用的方法

 Stream提供了一些便利的方法

    map()  映射
    filter() 过滤/筛选
    limit() 限制数量
    skip()  跳过数量
    reduce() 归约
    distinct() 去重
    sorted()  排序
    collect() 收集 结合Collectors.toList()使用
    forEach() 遍历
    ...  

 4.Stream流的中间操作

Stream流的中间操作,就是这个操作返回还是一个Stream流,不是一个最终结果,中间操作比如要有一个终止操作的方法调用才会执行

Stream流的中间操作 分为2类 无状态操作:当前的操作和其元素的前后没有依赖关系
 有状态操作:当前的操作的结果需要依赖其他的元素Xnip20200222_093836.png

 5.Stream流的终止操作

Stream流的终止操作,会返回一个最终的结果,只有有终止操作 中间操作才会执行

Stream流的终止操作 分为2类非短路操作:当前操作中间是不会断的,也就是需要流中的数据全部执行完毕短路操作:当前操作不需要等待全部数据执行完毕,可能到某个数据执行完毕后就结束流Xnip20200222_094611.png

 6.筛选和切片

  • filter
  • distinct
  • limit
  • skip
    

 准备数据

        //id name age 对应属性
        Student student = new Student(1, "johnny", 23);
        Student student1 = new Student(2, "candy", 25);
        Student student2 = new Student(2, "ruby", 25);
        Student student3 = new Student(3, "lucy", 33);
        Student student4 = new Student(4, "jack", 53);
        List<Student> studentList = new ArrayList<>();
        studentList.add(student);
        studentList.add(student1);
        studentList.add(student2);
        studentList.add(student3);
        studentList.add(student4);


        
  6.1 谓词筛选 filter

  Stream 接口支持 filter 方法,该操作会接受一个谓词(一个返回 boolean的函数)作为参数,并返回一个包括所有符合谓词的元素的流。

  如下:这个谓语就是 age>25

      List<Student> filterStudent = studentList.stream().filter(s -> s.getAge() > 25)
                .collect(Collectors.toList());
  6.2 筛选重复 distinct

Stream 接口支持 distinct 的方法, 它会返回一个元素各异(根据流所生成元素的 hashCode和equals方法实现)的流

       //得到Student所有的年纪并且去重
       List<Integer> ageList  = studentList.stream().map(s -> s.getAge())
                .distinct()
                .collect(Collectors.toList());
  6.3 限制元素 limit

Stream 支持limit(n)方法,该方法会返回一个不超过给定长度的流。所需的长度作为参数传递 给limit。如果流是有序的,则最多会返回前n个元素

        List<Integer> limitAgeList = studentList.stream().map(s -> s.getAge())
                .limit(2)
                .collect(Collectors.toList());
        System.out.println(limitAgeList);
6.4 跳过指定数量元素

  Stream 支持 skip(n) 方法,返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一 个空流。

        List<Integer> skipAgeList = studentList.stream().map(s -> s.getAge())
                .skip(2)
                .collect(Collectors.toList());

 7.映射

  • map
  • flatMap
  7.1 map

  Stream 支持 map 方法,它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映 射成一个新的元素

        List<Integer> mapAageList = studentList.stream().map(s -> s.getAge())
                .collect(Collectors.toList());
  7.2 flatMap

  Stream 流支持 flatmap 方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流

  注意 chars()方法返回的是IntStream ,需要装箱 boxed,转换为Stream,因为IntStream并不是Stream的子类

  下面的例子flatMap就是 分别把 前2个 student的name属性转换为一个流,并且将其合为一个流

        List<Integer> flatMapList = studentList.stream()
                .limit(2)
                .flatMap(s -> s.getName().chars().boxed())
                .collect(Collectors.toList());
        flatMapList.stream().forEach(i -> System.out.println((char)i.intValue()));

 打印

    j
    o
    h
    n
    n
    y
    c
    a
    n
    d
    y

 8.查找和匹配

  • anyMatch
  • allMatch
  • nonMatch
  • findAny
  • findFirst
  8.1 anyMatch

  流中是否有一个元素能匹配给定的谓词,有则返回true 否则返回false。

        //anyMatch 查找流中是否有满足谓语的,存在就返回true 否则就返回false
        boolean isExistAgeUp50 = studentList.stream()
                .anyMatch(s -> s.getAge() > 50);
  8.2 allMatch

  流中是否有所有元素能匹配给定的谓词。

        boolean allMatchFlag = studentList.stream()
                .allMatch(s -> s.getAge() > 10);
  8.3 nonMatch

  流中是否有没有任何元素能匹配给定的谓词。

        boolean noneMatchFlag =  studentList.stream()
                .noneMatch(s -> s.getAge() > 100);
  8.4 findAny

  findAny 方法将返回当前流中的任意一个元素。注意在非并行流下大多情况返回第一个元素,但是不保证

           Optional<Student> studentOptional =  studentList.parallelStream()
                .findAny();
  8.5 findFirst

  findFirst 方法将返回当前流中的第一个元素。

         studentList.stream()
                .map(s->s.getAge() * 2)
                .filter(i -> i % 2==0)
                .findFirst().ifPresent(i -> System.out.println(i));

 9.归约

  • reduce

 就是把一个流中的元素 经过lambda反复进行操作,指到流被归约成一个值

 reduce方法有3种形式:

Xnip20200222_110633.png

 把一个流中的元素组合起来,使用 reduce 操作来表达更复杂的查 询,比如“计算菜单中的总卡路里”或“菜单中卡路里最高的菜是哪一个”。此类查询需要将流中所有元素反复结合起来,得到一个值,比如一个Integer。这样的查询可以被归类为归约操作 (将流归约成一个值)。

 reduce方法接受两个参数:一个初始值,这里是0;一个 BinaryOperator 来将两个元素结合起来产生一个新值, 这里我们用的是 lambda (a, b) -> a + b。

      List<Integer> nums = Arrays.asList(3, 4, 5, 6, 7);
        int sum = nums.stream().reduce(0, (a, b) -> a + b);

 10.排序

  • sorted

 下面代码以自然序排序一个list

    list.stream().sorted()

 自然序逆序元素,使用Comparator 提供的reverseOrder() 方法,前提是流中的元素要实现了Comparator接口,比如Integer 这种

    list.stream().sorted(Comparator.reverseOrder())

 使用Comparator 来排序一个list

    list.stream().sorted(Comparator.comparing(Student::getAge))

 把上面的元素逆序

    list.stream().sorted(Comparator.comparing(Student::getAge).reversed())

 案例:将按照学生的Age属性排序 和 倒序

           studentList.stream()
                .sorted(Comparator.comparing(Student::getAge))
                .forEach(System.out::println);
        studentList.stream()
                .sorted(Comparator.comparing(Student::getAge).reversed())
                .forEach(System.out::println);

 11.收集

  • collect

 将流元素进行中间操作后进行收集到一个List 或者Set 中去,结合Collectors的方法

        studentList.stream()
                .map(Student::getAge)
                .collect(Collectors.toList());
        studentList.stream()
                .map(Student::getAge)
                .collect(Collectors.toSet());

 12.总结

 本篇主要讲解JDK8中 Stream流的使用,流是什么 如何创建 以及常用方法 包括如何 筛选 、切片、映射 、查找、匹配 、归约 等等 每个类型都会有对应的案例 简单易懂。

个人博客网站 https://www.askajohnny.com 欢迎来访问!

本文由博客一文多发平台 OpenWrite 发布!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值